If Perl were smarter about references

I wish that Perl 5 could be smarter about references. I wish I could just give an array reference to functions that only act on arrays and have Perl do the dereferencing for me.

Here is what I have to write today to use array functions on an array reference:

# Given $obj->foo() that returns an array reference

shift @{ $obj->foo };
push @{ $obj->foo }, @stuff;
splice @{ $obj->foo }, 0, 2;

Here is how I wish it would work:

shift $obj->foo;
push $obj->foo, @stuff;
splice $obj->foo, 0, 2;

Isn't that second block a lot cleaner to read? Getting rid of the @{} declutters the code and, at least for me, it's still clear from the context that I expect the first argument to act like an array.

Likewise, I'd like to have the same magic work for functions like values or keys, which would let me flatten array references or get an index list in a more readable way:

# from this:
for ( @{ $obj->foo } ) { ... }
for ( $#{ $obj->foo } ) { ... }

# to this:
for ( values $obj->foo ) { ... }
for ( keys $obj->foo ) { ... }

I suspect something similar would make sense for hash references, too.

On reflection, I think this would mean that checking that the first argument indeed held an array reference would have to be done at run-time, but I suspect there might be a way within the Perl op-codes to avoid such a checks except when necessary. (Thus, you could still use @{} for a slight bit of hand-optimization, if desired.)

I wish I knew more Perl guts to work on a draft implementation, because right now I think this would be one of the coolest features to see in a future Perl.

This entry was posted in perl programming and tagged , . Bookmark the permalink. Both comments and trackbacks are currently closed.

8 Comments

  1. Posted August 17, 2010 at 12:15 am | Permalink

    Why not use autobox? For example:

    for ($obj->foo->values) { ... }

    —Theory

    • dagolden
      Posted August 17, 2010 at 7:38 am | Permalink

      It's not core. (At least, not yet.) And it works through method resolution, and I don't think the overhead should be necessary for simple array manipulation. autobox is a great tool because Perl isn't smart enough about references.

  2. Posted August 17, 2010 at 2:23 am | Permalink

    Theory: Because of the performance penalty.

    I quite like the alternative syntax, but only if the run-time speed for shift @whatever is absolutely the same.

    I really don't want to pay a speed penalty for some of the most heavily used functions in the entire language.

  3. mirod
    Posted August 17, 2010 at 4:05 am | Permalink

    Amen, the @{ } syntax has always struck me as the ugliest part of Perl by far. Especially for references in a hash push @{ $foo->{bar}}, 1 is really, really ugly. I understand that in the case of for ($foo->{bar}) { ... } there would be an ambiguity, but really, how often do you do this to get the reference in $foo->{bar} in $_?

  4. Posted August 17, 2010 at 4:16 am | Permalink

    hello,

    Even i'm boring about writing/reading the @{ } stuff, i have to say i really appreciate the presence of the sigil because it make the code more readable (@ so you know it's an array) and reliable (@ so perl can crash if not an array).

    what i would like to see is @$obj->foo

  5. Posted August 17, 2010 at 4:19 am | Permalink

    @mirod: really: i use it daily !

  6. Posted August 17, 2010 at 4:27 am | Permalink

    What happens if $obj->foo returns multiple values?

    What will push foo(), @bar, @baz do if foo returns the empty list? And depending on the answer to that one: what will it do if the first element in @bar is an array ref?

    Then, whatever behaviour you pick: how do you explain it to a less experienced programmer who has to maintain some Perl code?

    (This feels a little like the Perl 6 RFC process all over…)

    A while back I saw a proposal to have $foo->@ mean @{ $foo }, so that your examples would become eg. push $obj->foo->@, @stuff. To me that seems more likely to work without wonderfully strange new corner cases. Though still slightly cumbersome, it still simplifies the syntax (just a postfix, instead of a circumfix around arbitrarily large expressions). And it also has the advantage of being available in places other than a handful of magic built-ins.

    • dagolden
      Posted August 17, 2010 at 7:48 am | Permalink

      In your first two examples, I would expect it to work just the exact same way that @{ $obj->foo } would work if foo() returned multiple values or an empty list.

      In your third example, if the first element of @bar is an array ref, it's pushed onto the array, just like normal. I'm only suggesting letting the target of the push be an array reference, because that's the only place where the intention is clear by context.

One Trackback

© 2009-2014 David Golden All Rights Reserved