Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl shorthand doubts

Tags:

perl

I have never really learnt Perl in any great depth but am doing a course through my work (can I say "just for fun"?). I understand the basics without any major problem but am now learning about references and shorthand. I have a doubt regarding the shorthand for arrays and accessing a referenced value, consider the two scripts below:

  1.  

    @Codes =
            (
             ["A1W",
              ["A2Q","A2Z"]],
             ["B2R","BB3"]
            );
    $CodeRef = \@Codes;
    
    #full notation
    print @{@{@{$CodeRef}[0]}[1]}[1], "\n";
    
    #shorthand notation
    print $CodeRef->[0]->[1]->[1], "\n";
    
  2.  

    my $BookPageArray;
    {
            $AnotherArray = [24, 18, 36]; 
            $Reference = \$AnotherArray; 
            $BookPageArray = \$AnotherArray; 
            $AnotherArray = [53, 256, 42];  count drops to 0
    }
    undef $Reference;
    print ${$BookPageArray}->[0]."\n";
    

My question is why in the second example does the $BookPageArray reference in the final print statement require curly brackets around it whereas in the first example the $CodeRef reference does not?

If I take out the curly brackets and the preceding $ sign in the second example it tells me there is no array located at that reference...

Is it to do with the fact that the second example is using anonymous data?

like image 842
user2960649 Avatar asked Nov 29 '22 12:11

user2960649


1 Answers

Woo, that's awful code! I know it's not your fault.

References are usually to arrays or hashes, but $BookPageArray is a reference to a reference to an array reference. Is this showing off or suppose to be teaching you?

Curly braces are like parentheses around mathematical expressions. They may help clarify or obfuscate.

my $answer = 3 + 4 x 5 + 6;          # Example 1
my $answer = 3 + ( 4 x 5 ) + 6;      # Example 2
my $answer = ( 3 + 4 ) X ( 5 + 6 );  # Example 3

Example 1 and Example 2 are the same. Do the parentheses clarify? You could argue they do. In Example 3, the parentheses are necessary.

my $answer = 1 + 3 + 4 + 9 + 10;
my $answer = ( ( ( ( 1 + 3 ) + 4 ) + 9 ) + 10 );

Again, these are both the same. The question is whether the parentheses clarify what is going on (they don't) or make it harder to understand (they do).

These are equivalent too:

print $foo . "\n";
print ${foo} . "\n";

The curly braces can help in certain situations:

print "The file name is ${foo}_bar.txt\n";

Here, you need curly braces in order to let Perl know that the variable is $foo and not $foo_bar. These are equivalent:

print "The file name is ${foo_bar}.txt\n";
print "The file name is $foo_bar.txt\n";

So, in your statement you have:

${$BookPageArray}->[0]."\n";

Some people like this because it helps emphasize that ${BookPageArray} is a scalar reference and helps you see that this reference is being dereferenced:

${$BookPageArray}->[0]."\n";   # I see that this is a scalar reference being dereferenced
$$BookPageArray->[0]."\n";     # Didn't notice the `$$`, so missed the dereferencing.
${${$BookPageArray}}[0]."\n";  # Yes, this is the same thing!

The arrow -> syntax can help clarify things when you dereference arrays and hashes.

my $value = $foo->{BAR};    # I can see that `$foo` is a reference to an array!
my $value = ${${foo}}{BAR}; # Ow! This hurts my brain
my $value = $$foo{BAR};     # Easier on the brain, but I'll miss that `$foo` is a ref.

These are all equivalent, but that first one is the easiest to understand. Unfortunately, there's no -> equivalent for dereferencing scalars. Fortunately, it's not done all that often.

Most of the time, referencing is simply done to create complex data structures:

my $person = {};  # This will be a hash reference (not necessary)...
$person->{NAME} = "Bob";
$person->{ADDR} = "123 Testing Ave.";
$person->{CITY} = "New York";
$person->{STATE} = "CA"; #Got you!
$person->{PHONE} = [];  # Array Reference (not necessary)
$person->{PHONE}->[0] = {}; # Hash reference (not necessary)
$person->{PHONE}->[0]->{TYPE} = "cell";
$person->{PHONE}->[0]->{NUMBER} = "555-1234";

You can see in this structure, I have a person with a name, address, and multiple phone numbers.

I don't have to declare something to be an array reference or a hash reference, but it can sometimes clarify what you're storing. The my $person = {}; is not necessary. I could have done just my $person, but it helps clarify that it's a reference you're using. Declaring an array reference for the phone numbers probably adds more smoke than light, and should not be done. The declaration of $person->{PHONE}->[0] to be a hash reference really just detracts from what is going on.

I suggest the builtin Perl reference tutorial. It's straight forward and easy to understand. I also recommend you get a good book on Modern Perl since Perl's coding style and syntax has changed since Perl 3.x that many Perl books still seem based upon.

After you get comfortable with references, you should read the Object Oriented Perl tutorial. Object Oriented Perl is basically creating complex data structures using references, but doing it in a way that makes it easy to track complex structures.

It gets a bit complex to keep track of something like this: $person->{PHONE}->[0]->{NUMBER} = "555-1234";

like image 108
David W. Avatar answered Dec 06 '22 07:12

David W.