Mar 2, 2021, 11:30 AM
Post #5 of 14
(943 views)
Permalink
On 2021/02/28 09:30, Ricardo Signes wrote:
> On Sun, Feb 28, 2021, at 2:21 AM, L A Walsh wrote:
>> It seems all of the reasons against auto-deref were answered in-so-much
>> that that claims of ambiguity were shown not to exist. For example, in
>> the case of use of 'keys'. Without autoderef, the language requires
>> a perlvar of type ARRAY or HASH with a '@' or a '%' in front of it.
>> Autoderef only supported the option of having a reference to something
>> that would have had an '@' or a '%' in front of it. Since perl always
>> knows the type of vars having an '@' or '%' in front of, then
>> a reference to either can automatically, and unambiguously always be
>> assumed to be of type that would have had an '@' or '%'.
>>
>> So can I ask that it's removal be undone?
>
> The short answer is: this just isn't happening.
>
> I think, but am not sure, that you're a bit confused about the
> realities of the ambiguity of autoderef. Some built-ins can work on
> both hashes and arrays. These include "keys" and "each" and
> "values". (I think that's it.) Also, via overloading, a reference
> may be able to function as both a hash and array reference. Consider
> this program:
>
> use v5.14.0;
> no v5.16.0;
>
> package Weird {
> use overload '@{}' => sub { [ 1, 2, 3, 4 ] },
> '%{}' => sub { { (a=>1, b=>2) } };
>
> sub new {
> my $val = "Meaningless.";
> bless \$val, 'Weird';
> }
> }
>
> my $aref = [ 1, 2, 3, 4 ];
> my $href = { a => 1, b => 2 };
> my $weird = Weird->new;
>
> say "A $_" for keys $aref;
> say "H $_" for keys $href;
> say "W $_" for keys $weird;
>
>
> What should the "W" behavior be?
----
Type of argument to keys on reference must be unblessed hashref or
arrayref at /tmp/rtest line 32.
The behavior should be exactly what is documented. The documentation
says that the refs must be to natural or native @arrays
or %hashes. No other usage is possible. I appreciate your usage of code
to explain the problem, but you are asking the perl language to define case
'W' when it _is_defined_ not to know.
Case A, the language, it knows it is a ref to native type ARRAY.
Case H, the language, the interp knows is a ref to a native type HASH.
Case W, though isn't defined **IN THE LANGUAGE**. Therefore interpreter
CANNOT process it where only an ARRAY (X)OR HASH is required. Note, the
language
only accepts one of 'ARRAY' or 'HASH', not both. It is an XOR operation.
Thus any reference to something that is not, strictly a native ARRAY or
a native HASH must be rejected.
Case W is neither a native ARRAY nor a HASH.
In the above, you can also write this:
Perl defines autoderef to only work when the following
is true for $Xref when the following resolves to an ARRAY or a HASH.
do {
my $t=ref $XREF;
if ($t eq HASH) { %$ref }
elsif ($t eq ARRAY) { @$ref }
else { $ref }
};
If '$Xref' is not reference to a perl-defined type of ARRAY or HASH,
then it is disallowed.
As I've stated before, the only reason detractors have given for
allowing this is that they/you want the deref to work in the
case that _perl_ _doesn't_ _support_. This is a limitation of perl, not
of auto-deref. Perl cannot dereference something that is not already
defined as a type in the language.
A user defined object creates a 'Type' of data that doesn't purely
adhere
to the rules for a native type. Thus perl cannot treat it as one. It makes
no difference that the implementor _wanted_ it to be like an ARRAY or
like a HASH, the implementor has no way of telling perl what they mean other
than by overriding perl's operators and functions to do what they want.
If they want 'Weird' to operate in a specific way, they need to define
that method in their class.
package Wierd;
sub keys($) {
my $w=shift;
if (ref $w ne 'Wierd') { die "Weird::keys only knows about Weird
refs"; }
do { ...whatever Wierd wants }
}
> In reality, the decision was that to avoid ambiguity, this would be
> fatal.
---
In truth, it is only ambiguous because the creator was ambiguous -- not
autoderef. The creator of the class didn't define its behavior in such
a case.
It is a _user_ error to use 'keys' where a method has not been defined.
Perl only defines usage of keys with native ARRAY or HASH's. If a
class-creator
wants to have their class work with keys, they need to define their own key
method.
> That means that if you're going to allow things that provide an array
> ref or hash ref interface, but are not unblessed references, you must
> add the dereference yourself: ...
---
If they want their class to operate with a perl "operator (or
function)"
they need to define the method.
If a user creates a class Complex, and uses 'overload' to provide
methods
for it to work with '+' and '-', how is this any different?
Natively if the creator doesn't define usage for '+' or '-', and they
try to add a value of type 'Complex', it won't work;
To be consistent, you need to disable native '+' and native '-' working
with unblessed integers and floats.
Note, that 'ref $integer' and 'ref $float' return no type. yet
creators of
a class 'Complex' that works with '+' or '-' can only provide
functionality that
works with a reference to their class.
In the case of native ARRAY and HASH, perl, unambiguously returns ARRAY
and HASH -- perl's own data types that it can provide methods for.
All the autoref detractors need to do is provide a method to work when
a ref '$Xref' returns 'Weird' and they are set. End of story.
It is not the case that use of 'autodef' leads to unambiguous behavior,
unless the class designer has not defined the behavior. This is neither a
failing of language nor autoderef, but of the class designer in
neglecting to
define analogous behavior.
How can the language define an operation for an arbitrary class when the
designer of the class has not or _can_ not define that behavior? Detractors
are complaining that perl only defines actions for its own types. So? How
is that a problem? The designers of such types can define actions -- yet
choose not to. How is that a failure defining how native
operator/functions operate on perl-native or ref-to-perl-native types
operate?