sectokia has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks, Given anonymous structures like:

my $array = [qw(a b c)]; my $hash = { a => 1, b => 2, c => 3 };

Is there a technical reason so many people/books use:

print $array->[2]; print $hash->{a};

Instead of saving 1 character and using:

print @$array[2]; print %$hash{a};

Replies are listed 'Best First'.
Re: dereferencing question
by ikegami (Patriarch) on Jan 17, 2025 at 12:15 UTC

    First of all,

    print $array->[2]; print $hash->{a};
    is equivalent to
    print $$array[2]; print $$hash{a};

    So this is what we're going to compare.

    I find the former much more readable, and I'm sure I'm not the only one.

    The former reads from left to right. That latter requires reading the whole thing to understand what it is. And it requires knowing whether $$array[2] means ${$array[2]} or ${$array}[2]. (To add further confusion, it's the opposite of the C equivalent.) You could use ${$array}[2] to address the later problem, but now you have an even bigger mess of symbols, it's still not 100% clear to the less experienced, and you're using an extra character.

Re: dereferencing question
by swl (Prior) on Jan 17, 2025 at 05:31 UTC

    The @ and % sigils indicate you want a list and not a scalar.

    If you use an array directly then you get a warning. I'm not sure why it does not appear for array derefs.

    perl -E"use warnings; my @array = (1..3); print @array[2];" Scalar value @array[2] better written as $array[2] at -e line 1.
Re: dereferencing question
by talexb (Chancellor) on Jan 17, 2025 at 16:54 UTC

    The whole 'saving 1 character' thing isn't really the space saving that people think it is. I started programming in the 70's, and even then we didn't worry about how much space a source code file took up, and that was with disks that were measured in 10-20 megabytes. That's storage -- data transmission isn't something anyone worries about -- I just finished a three way video call that ran for half an hour. I have no idea how much bandwidth that took, but it completely overwhelms any space saving that might have been realized by 'saving a character'.

    Finally, my favorite reason: writing software targets two different goals: Communicating efficiently and accurately with a computer, and communicating clearly with future developers (that may include you when you have to go back over your code to understand what you were thinking when you wrote it). The computer only cares if the code compiles and runs. If the source code is clear and legible, future developers will quickly be able to understand how it works. If there's a little obfuscation, that's not going to affect the computer, but it's definitely going to slow things down with reader comprehension.

    The print command is expecting a scalar; if you pass it an array, you may not get what you're expecting:

    DB<1> $array = [qw(a b c)]; DB<2> $hash = { a => 1, b => 2, c => 3 }; DB<3> print $array->[2]; c DB<4> print $hash->{a}; 1 DB<5> print @$array[2]; c DB<6> print %$hash{a}; a1 DB<7>
    So -- I imagine that the last print statement didn't output what you were expecting. And those second two print statements are less clear than the first two. The form $array->[2] is much clearer than @$array[2] or $$array[2] (from ikegami, above). I would even argue that 'array' is a misnomer, because it's actually an array_ref (a reference to an array).

    Clarity in writing software is paramount. Having to wade through some 'clever code' can be a real challenge; it's worse when it's your own code, because someone wise once said that you have to be twice as smart to debug something as you do to write it in the first place.

    Alex / talexb / Toronto

    For a long time, I had a link in my .sig going to Groklaw. I heard that as of December 2024, this link is dead. Still, thanks to PJ for all your work, we owe you so much. RIP Groklaw -- 2003 to 2013.

      communicating clearly with future developers

      And also search tools, code prettyfiers and the occasional perl script to mass-update existing code bases for more modern Perl idioms¹. The more unique (and standardized across the whole codebase) a construct is, the easier it is to find, even with non-regex searches.

      It's basically the same reason for naming a variable @customers instead of @c: Easier to understand, and much more important, easier to find.


      ¹ Converting to sub signatures, which (mostly) worked and saved me many days of manual editing.

      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
      Also check out my sisters artwork and my weekly webcomics

        The only time I use single character variable names like $k is when the scope is going to be something really small like five to ten lines. For example,

        foreach my $k ( keys %DBhandles ) { $DBhandles{ $k }{ sth }->finish; $DBhandles{ $k }{ dbh }->disconnect; }
        And yes, I could minimize that to just using $_ instead of $k, but I try to never use that special variable, because it requires extra effort for the reader.

        Alex / talexb / Toronto

        For a long time, I had a link in my .sig going to Groklaw. I heard that as of December 2024, this link is dead. Still, thanks to PJ for all your work, we owe you so much. RIP Groklaw -- 2003 to 2013.

Re: dereferencing question
by GrandFather (Saint) on Jan 18, 2025 at 01:21 UTC

    See my sig vvvvvv.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond