How Perl’s dereferencing syntax is unnecessarily awful

Aristotle on 2007-10-16T02:02:48

Schwern wrote about how ugly “push @{ $foo{bar} }, 3” is. He proposes the use of autobox::Core to get around this.

Personally, I would have loved if prototypes did nothing else than coerce context and if the compiler assumed that scalars are already references of the appropriate type everywhere a reference is expected, including in prototypes such as “\@” that want to take a reference.

See, the prototype on push lets me write “push @foo, $bar” rather than “push \@foo, $bar”. But why not also let me write “push $foo, $bar”? It insists on the right sigil so the type can be checked; I mean, sure, $foo could be something other than an array ref.

So what? The compile-time check is satisfied if I say “push @$foo, $bar”, since it knows it will be able to take an array reference if $foo has dereferenced to an array. But the check whether $foo dereferences to an array in the first place will be performed at runtime anyhow!

So Perl might as well have let me say “push $foo, $bar” instead. The check ultimately happens at runtime, no matter what.

But that would allow me to write…

push $foo{bar}, 3;
# instead of
push @{ $foo{bar} }, 3;

# or even
delete $foo{bar}{qw( baz quux )}
# instead of
delete @{ $foo{bar} }{qw( baz quux )}

# and in fact,
join " ", $foo{bar}[ 3 .. 8 ]
# instead of
join " ", @{ $foo{bar} }[ 3 .. 8 ]

What purpose do all those spurious @{} serve? None. They literally add no information whatsoever to the code.

Perl code really does look kinda junky sometimes.

[NB.: those examples aren’t syntax errors in Perl – they just don’t do anything useful, and certainly not what you’d expect. So we can’t retroactively fix this in 5.12 or something. Sigh.]


But it's ambiguous...

mauzo on 2007-10-16T03:53:22

my @x;
undef @x;

my $x = [];
undef @$x;
undef $x;
Personally I think I'd prefer the syntax $a{foo}[] for @{ $a{foo} }; that might even be backwards-compatible. Of course, the heuristic that the parser uses to check the sigils would need completely changing, which would be a nasty job, and you lose the human-heuristic that 'if it starts with @ it's multiple-valued' which was the whole point of the multiple deref operators in the first place.

Re:But it's ambiguous...

Aristotle on 2007-10-16T04:12:58

undef @$x;

Good catch – if you need to dereference a ref without using a [] or {} indexing operation, you need the @{} bracket. I guess that explains the ugly new syntax in Perl 6.

I guess ${} is always necessary by the same token.

All in all, not the majority of cases.