develooper Front page | perl.perl5.porters | Postings from April 2018

Re: [perl #133109] push on scalar forbidden: why?

Thread Previous | Thread Next
From:
L A Walsh
Date:
April 22, 2018 02:57
Subject:
Re: [perl #133109] push on scalar forbidden: why?
Message ID:
5ADBF9F0.2040704@tlinx.org
Dave Mitchell via RT wrote:
> On Sat, Apr 21, 2018 at 02:10:05PM -0700, L A Walsh wrote:
>   
>> Two answers.  The first answer: it never gets that far.
>>
>> PERL5OPT="" perl /tmp/ovld.pl
>> Not an unblessed ARRAY reference at /tmp/ovld.pl line 9.
>>     
>
> That's because specifically to get round the problem of the overloading
> ambiguity, the perl autodedef ref implementation was changed so that it
> croaked on blessed refs.  This made things even worse - 
>   
It would make the new perl incompatible with old code.  One of the
rules in the proposed change was that "push $_,3" should be have identically
to push @$_,3 at runtime.  That change broke compatibility and doesn't
really protect from the problem it was trying to fix since putting a '@' 
in front overrides the restriction in the statement that died.

>  tperl
P "hello from perl %s", $];
my $aref;
bless $aref=[], "SomeClass";
push @$aref, 3;
P "bye world, aref = %s", $aref;
'
hello from perl 5.016003
bye world, aref = SomeClass[3]    # <-- result: blessed array (CLASS[])
                                  # w/3 pushed on

I'm guessing where this feature was really meant to "fix" things was
in this statement:
    @k = keys $r;

as I think I understand it, only if the ref is in a class can it
use overloading(?), and the bless-check stopped that in:

Type of argument to keys on reference must be unblessed hashref or 
arrayref at /tmp/ovld.pl line 11.

Again, I think checking if there was a bless on the ref was a bit of a
hack, since it "avoided" the problem rather than dealing with it.

In that scenario, blessed or not, the only way it could be resolved is
if perl knew '$r' was one type or the other.  Since it can't know, the
programmer needs to resolve that by adding a sigil (either statically,
or at runtime using an eval:

my @k;
if ($wantref eq ARRAY) {
    eval {@k = keys @$r};
} else {
    eval {@k = keys %$r};
}

or something similar.  If you are looking for a compile time
error message, like the primitive syntax check of push/pop @[$]ref
forcing '@', it can't really happen.  Perl is a loosely typed language.
It's usually some special case where it can type check at 'compile time'.
But those special cases also become hard-coded limitations that can
prohibit other options.




"

>  This made things even worse - you could never
> use the new syntax in any place where there was a possibility that the
> ref you get passed may have been blessed. This was a big motivation for
> eliminating the feature.
>
>   
>> 2nd answer -- this was brought up by Dan Brook.  I answered:
>> In any case where there is ambiguity, the compiler must throw an error(like):
>>
>> Ambiguous dereference @ line 13: Sigil required.
>>
>> My suggestion was to auto-dereference references where perl knew the type
>> of the reference.  If it reference is ambiguous, it can't know the type.
>>     
>
> Since perl almost never knows the type of a reference at compile-time,
> how can this ever work? Can you give a more concrete example?
>   
---
    It works for giving a runtime error just like:

    my $r={};
    push @$r;

does now.  It can't be detected until runtime if you want to use
use runtime references.  If forcing the addition of '@' is important,
perhaps that could be toggled via a pragma, but adding '@' won't guarantee
that it will work at runtime as in the example above.  The compiler
can only do static/syntax checks, which may give warm fuzzies, but may
mislead some people if they think it prevents runtime errors.

Adding the "overload" module simply allow more options for runtime errors
and in those cases, the requirement for using explicit '@' or '%' can not
go away because it creates a runtime ambiguity that the runtime can't 
resolve
and would have to flag as an error at runtime.
>
> Do you mean as a compile-time error or a run-time error?
>   
run-time -- just as the above example generates now.


No algorithm will work for all input.  That doesn't mean you throw out
division because you can't divide by 0.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About