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

Oh, wise monks. There are a few things that elude me... I wish to ask you them now in the no particular order.

1st Question
Why can I say this:

print "Just another @{[ (localtime)[5] ]} Hacker"?
What is going on with @{[ ]}? It seems like you are creating an anonymous array reference [] and dereferencing it with @{}. But how does this make since in that context? I am confused...

2nd Question
Look at this code:

(caller 0)[3] (localtime)[5]+1900
What's confusing me in both lines are the parentheses (). Why have them here? What are they doing in this context?

Replies are listed 'Best First'.
Re: Questions about context
by Errto (Vicar) on Jan 30, 2005 at 01:14 UTC

    You are correct about what the @{ [ ] } syntax does in your first question. The reason it's written like that is twofold: first, you're trying to call a function within a string interpolation, which simple interpolation of scalar variables and the like doesn't allow. However, you can interpolate an array constructed on the fly just like you have. Second, the code (localtime)[5] means: evaluate the function localtime in list context, and then take the sixth element of the list that it returns. This also explains what is going on in your second example. This is known as a list slice and is explained in more detail in the "Slices" section of perldata.

    Update: Thought I'd add some examples. As you've mentioned,

    my $x = (localtime)[0];
    works by taking a list slice, thus forcing localtime to be called in list context. The behavior of a list slice in scalar context, however, is to return the last element of the list, so
    my $x = (localtime)[2,3,4,0];
    would have the same result as the above. Another way to do it is
    my ($x) = localtime;
    This is different. There's no slice here. Instead, the parentheses around the left-hand side of the assignment force the right side to be evaluated in list context, and then the first element returned is assigned to the first scalar lvalue on the left side. BUT, parentheses do not always mean list context. In particular,
    my $x = (localtime)
    will not do the same thing. Instead it will call localtime in scalar context and assign the result to $x.

      Ah, I see, so it's kind of a trick: you create an anony array reference and then you dereference it, so it's like it never existed! The only point was to interpolate what was inside.

      Would it work if I used an anony hash reference, instead of an array reference? For example:

      %{ { (localtime)[5] } }

        Hashes don't interpolate in double-quoted strings. That's the first reason it doesn't work. The second reason is that hashes need an even number of elements, and you're generating an odd number of elements.

        To illustrate both of those points, try the following:

        my %hash = ( one => 1, two => 2 ); print "%hash\n"; # See, it doesn't interpolate. %hash = ( localtime )[5]; # Now you get a warning about uneven number +of elements.

        Far more than you ever wanted to know about string interpolation is described in perlop.


        Dave

        No, that does not work.
        But you can write  print "@{[ %x ]}" if you want.
        Boris
        No, hashes don't interpolate into double-quoted strings in perl5. But you can use a scalar de-ref/ref:
        print "year is ${\((localtime)[5]+1900)}!\n";
Re: Questions about context
by Revelation (Deacon) on Jan 30, 2005 at 20:15 UTC
    It's important to note that arrays and lists are not equivalent. With regards to  (caller 0)[3] and (localtime)[5]+1900 the parentheses are forcing the evaluation of the list like an array. Lists, which are usually diagramed as  (LIST) in Perl can be subscripted like a normal array. However, to do so the a slice syntax is used, which takes the form  @result/$result = ( LIST ) [ LIST ];. The parens are used to avoid ambiguity. Merlyn could further clarify.

    Thus,
    my $scalar= ( EXPR )[0];
    is the rough equivalent of:
    my $scalar; { my @expr = EXPR(); $scalar = @expr[0]; # or $expr[0]; }

    Gyan Kapur
      (localtime)[5]+1900 the parentheses are forcing the evaluation of the list like an array.

      It is a misleading statement. The parentheses are only for grouping. localtime[5] will convert [5] into an array of date and time elements. This is not what you want because [5] is not a reasonable thing to convert to a time.

      The parentheses are only to get localtime to be called without an argument.

      Enclosing parentheses don't change context. Look up the dual-nature comma operator to understand lists and their parentheses. That the standard (i.e. Camel) example of a list includes parentheses doesn't aid proper understanding of this issue. But it is impressive how the dwimery works in spite of this.

      Be well,
      rir