diff options
author | Ricardo Signes <rjbs@semiotic.systems> | 2020-09-06 20:25:23 -0400 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2020-09-06 20:47:53 -0600 |
commit | 53e62bf8898afdc5cca37743a682b655dbe42614 (patch) | |
tree | 47df42645be7f39ed961bd67031fa7dee72641c8 /pod/perldsc.pod | |
parent | 748e249cf0d014c60e338b49bd0ef4c5af880325 (diff) | |
download | perl-53e62bf8898afdc5cca37743a682b655dbe42614.tar.gz |
perldsc: in general, prefer postfix to circumfix dereference
In all (or almost all) cases, postfix dereferencing is simpler to read
and write. This makes it the better choice for teaching new Perl
programmers.
I have left in reference to circumfix deref, but mostly to acknowledge
that it exists, not to suggest its use.
Diffstat (limited to 'pod/perldsc.pod')
-rw-r--r-- | pod/perldsc.pod | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/pod/perldsc.pod b/pod/perldsc.pod index 7564b97ccc..832835b5b5 100644 --- a/pod/perldsc.pod +++ b/pod/perldsc.pod @@ -183,31 +183,30 @@ The square brackets make a reference to a new array with a I<copy> of what's in @array at the time of the assignment. This is what you want. -Note that this will produce something similar, but it's -much harder to read: +Note that this will produce something similar: # Either without strict or having an outer-scope my @array; # declaration. for my $i (1..10) { @array = 0 .. $i; - @{$AoA[$i]} = @array; + $AoA[$i]->@* = @array; } Is it the same? Well, maybe so--and maybe not. The subtle difference is that when you assign something in square brackets, you know for sure it's always a brand new reference with a new I<copy> of the data. -Something else could be going on in this new case with the C<@{$AoA[$i]}> -dereference on the left-hand-side of the assignment. It all depends on -whether C<$AoA[$i]> had been undefined to start with, or whether it -already contained a reference. If you had already populated @AoA with -references, as in +Something else could be going on in this new case with the +C<< $AoA[$i]->@* >> dereference on the left-hand-side of the assignment. +It all depends on whether C<$AoA[$i]> had been undefined to start with, +or whether it already contained a reference. If you had already +populated @AoA with references, as in $AoA[3] = \@another_array; Then the assignment with the indirection on the left-hand-side would use the existing reference that was already there: - @{$AoA[3]} = @array; + $AoA[3]->@* = @array; Of course, this I<would> have the "interesting" effect of clobbering @another_array. (Have you ever noticed how when a programmer says @@ -241,12 +240,24 @@ much more easily understood constructors C<[]> and C<{}> instead of relying upon lexical (or dynamic) scoping and hidden reference-counting to do the right thing behind the scenes. +Note also that there exists another way to write a dereference! These +two lines are equivalent: + + $AoA[$i]->@* = @array; + @{ $AoA[$i] } = @array; + +The first form, called I<postfix dereference> is generally easier to +read, because the expression can be read from left to right, and there +are no enclosing braces to balance. On the other hand, it is also +newer. It was added to the language in 2014, so you will often +encounter the other form, I<circumfix dereference>, in older code. + In summary: $AoA[$i] = [ @array ]; # usually best $AoA[$i] = \@array; # perilous; just how my() was that array? - @{ $AoA[$i] } = @array; # way too tricky for most programmers - + $AoA[$i]->@* = @array; # way too tricky for most programmers + @{ $AoA[$i] } = @array; # just as tricky, and also harder to read =head1 CAVEAT ON PRECEDENCE X<dereference, precedence> X<dereferencing, precedence> @@ -269,9 +280,9 @@ dereference the thing at that subscript. That's fine in C, but this isn't C. The seemingly equivalent construct in Perl, C<$$aref[$i]> first does the deref of $aref, making it take $aref as a reference to an array, and then dereference that, and finally tell you the I<i'th> value -of the array pointed to by $AoA. If you wanted the C notion, you'd have to -write C<${$AoA[$i]}> to force the C<$AoA[$i]> to get evaluated first -before the leading C<$> dereferencer. +of the array pointed to by $AoA. If you wanted the C notion, you could +write C<< $AoA[$i]->$* >> to explicitly dereference the I<i'th> item, +reading left to right. =head1 WHY YOU SHOULD ALWAYS C<use strict> @@ -364,7 +375,7 @@ X<array of arrays> X<AoA> } # add to an existing row - push @{ $AoA[0] }, "wilma", "betty"; + push $AoA[0]->@*, "wilma", "betty"; =head2 Access and Printing of an ARRAY OF ARRAYS @@ -381,7 +392,7 @@ X<array of arrays> X<AoA> # print the whole thing with indices for $i ( 0 .. $#AoA ) { - print "\t [ @{$AoA[$i]} ],\n"; + print "\t [ $AoA[$i]->@* ],\n"; } # print the whole thing one at a time @@ -431,7 +442,7 @@ X<hash of arrays> X<HoA> } # append new members to an existing family - push @{ $HoA{"flintstones"} }, "wilma", "betty"; + push $HoA{flintstones}->@*, "wilma", "betty"; =head2 Access and Printing of a HASH OF ARRAYS @@ -443,31 +454,31 @@ X<hash of arrays> X<HoA> # print the whole thing foreach $family ( keys %HoA ) { - print "$family: @{ $HoA{$family} }\n" + print "$family: $HoA{$family}->@* \n" } # print the whole thing with indices foreach $family ( keys %HoA ) { print "family: "; - foreach $i ( 0 .. $#{ $HoA{$family} } ) { + foreach $i ( 0 .. $HoA{$family}->$#* ) { print " $i = $HoA{$family}[$i]"; } print "\n"; } # print the whole thing sorted by number of members - foreach $family ( sort { @{$HoA{$b}} <=> @{$HoA{$a}} } keys %HoA ) { - print "$family: @{ $HoA{$family} }\n" + foreach $family ( sort { $HoA{$b}->@* <=> $HoA{$a}->@* } keys %HoA ) { + print "$family: $HoA{$family}->@* \n" } # print the whole thing sorted by number of members and name foreach $family ( sort { - @{$HoA{$b}} <=> @{$HoA{$a}} - || - $a cmp $b + $HoA{$b}->@* <=> $HoA{$a}->@* + || + $a cmp $b } keys %HoA ) { - print "$family: ", join(", ", sort @{ $HoA{$family} }), "\n"; + print "$family: ", join(", ", sort $HoA{$family}->@* ), "\n"; } =head1 ARRAYS OF HASHES @@ -548,7 +559,7 @@ X<array of hashes> X<AoH> # print the whole thing with indices for $i ( 0 .. $#AoH ) { print "$i is { "; - for $role ( keys %{ $AoH[$i] } ) { + for $role ( keys $AoH[$i]->%* ) { print "$role=$AoH[$i]{$role} "; } print "}\n"; @@ -640,7 +651,7 @@ X<hash of hashes> X<HoH> # print the whole thing foreach $family ( keys %HoH ) { print "$family: { "; - for $role ( keys %{ $HoH{$family} } ) { + for $role ( keys $HoH{$family}->%* ) { print "$role=$HoH{$family}{$role} "; } print "}\n"; @@ -649,7 +660,7 @@ X<hash of hashes> X<HoH> # print the whole thing somewhat sorted foreach $family ( sort keys %HoH ) { print "$family: { "; - for $role ( sort keys %{ $HoH{$family} } ) { + for $role ( sort keys $HoH{$family}->%* ) { print "$role=$HoH{$family}{$role} "; } print "}\n"; @@ -661,7 +672,7 @@ X<hash of hashes> X<HoH> keys %HoH ) { print "$family: { "; - for $role ( sort keys %{ $HoH{$family} } ) { + for $role ( sort keys $HoH{$family}->%* ) { print "$role=$HoH{$family}{$role} "; } print "}\n"; @@ -678,7 +689,7 @@ X<hash of hashes> X<HoH> print "$family: { "; # and print these according to rank order for $role ( sort { $rank{$a} <=> $rank{$b} } - keys %{ $HoH{$family} } ) + keys $HoH{$family}->%* ) { print "$role=$HoH{$family}{$role} "; } @@ -709,7 +720,7 @@ many different sorts: $last = pop @ { $rec->{SEQUENCE} }; print $rec->{LOOKUP}{"key"}; - ($first_k, $first_v) = each %{ $rec->{LOOKUP} }; + ($first_k, $first_v) = each $rec->{LOOKUP}->%*; $answer = $rec->{THATCODE}->($arg); $answer = $rec->{THISCODE}->($arg1, $arg2); @@ -790,7 +801,7 @@ many different sorts: foreach $family (keys %TV) { $rec = $TV{$family}; # temp pointer @kids = (); - for $person ( @{ $rec->{members} } ) { + for $person ( $rec->{members}->@* ) { if ($person->{role} =~ /kid|son|daughter/) { push @kids, $person; } @@ -814,14 +825,14 @@ many different sorts: # print the whole thing foreach $family ( keys %TV ) { print "the $family"; - print " is on during @{ $TV{$family}{nights} }\n"; + print " is on during $TV{$family}{nights}->@*\n"; print "its members are:\n"; - for $who ( @{ $TV{$family}{members} } ) { + for $who ( $TV{$family}{members}->@* ) { print " $who->{name} ($who->{role}), age $who->{age}\n"; } print "it turns out that $TV{$family}{lead} has "; - print scalar ( @{ $TV{$family}{kids} } ), " kids named "; - print join (", ", map { $_->{name} } @{ $TV{$family}{kids} } ); + print scalar ( $TV{$family}{kids}->@* ), " kids named "; + print join (", ", map { $_->{name} } $TV{$family}{kids}->@* ); print "\n"; } |