from Programming Perl pg 90, he says:
@ary = (1, 3, sort 4, 2);
print @ary;
the commas on the right of the sort are evaluated before the sort but the commas on the left are evaluated after. ... list operators tend to gobble .. and then act like a simple term"
- Does the assignment result in sort being processed or does that happen when
@ary
is expanded by print? - What does he mean by all that "comma" stuff?? My understanding is that in the assignment statement, comma has a lower priority than a list operator therefore sort runs first and gobbles up it's arguments
(4 and 2)
.. How the heck is comma being evaluated at all?? So that statemnent then becomes (1, 3, 2, 4) a list which is assigned.. comma is just acting as a list separator and not an operator!! In fact on pg:108 he says: do not confuse the scalar context use of comma with list context use.. What is a leftward and rightward list operator?
print @ary
is a rightward list operator?? So it has very low priority?print($foo, exit);
here, how is precedence evaluated? print is a list operator that looks like a function so it should run first! it has two arguments $foo
and exit
.. so why is exit not treated as a s开发者_开发百科tring??? After all priority-wise print(the list operator) has higher priority??
print $foo, exit;
here, you have print and , operators but the list operator has higher precedence.. so.. exit should be treated as a string - why not??
print ($foo & 255) + 1, "\n";
here since it's a list operator it prints $foo & 255
Shouldn't something similar happen with the above mentioned exit
stuff..
When in doubt about how Perl is parsing a construct, you can run the code through the B::Deparse
module, which will generate Perl source code from the compiled internal representation. For your first example:
$ perl -MO=Deparse,-p -e '@ary = (1, 3, sort 4, 2); print @ary;'
(@ary = (1, 3, sort(4, 2)));
print(@ary);
-e syntax OK
So as you can see, sort
takes the two arguments to its right.
As far as execution order goes, you can find that out with the B::Concise
module (I've added the comments):
$ perl -MO=Concise,-exec -e '@ary = (1, 3, sort 4, 2); print @ary;'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s # start of list
4 <$> const[IV 1] s # 1 is added to list
5 <$> const[IV 3] s # 3 is added to list
6 <0> pushmark s # start of sort's argument list
7 <$> const[IV 4] s # 4 is added to sort's argument list
8 <$> const[IV 2] s # 2 is added to sort's argument list
9 <@> sort lK # sort is run, and returns its list into the outer list
a <0> pushmark s
b <#> gv[*ary] s
c <1> rv2av[t2] lKRM*/1
d <2> aassign[t3] vKS/COMMON # the list is assigned to the array
e <;> nextstate(main 1 -e:1) v:{
f <0> pushmark s # start of print's argument list
g <#> gv[*ary] s # the array is loaded into print's argument list
h <1> rv2av[t5] lK/1
i <@> print vK # print outputs it's argument list
j <@> leave[1 ref] vKP/REFC
-e syntax OK
For your second example:
$ perl -MO=Deparse,-p -e 'print $foo, exit;'
print($foo, exit);
-e syntax OK
$ perl -MO=Concise,-exec -e 'print $foo, exit;'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s
4 <#> gvsv[*foo] s # add $foo to the argument list
5 <0> exit s # call `exit` and add its return value to the list
6 <@> print vK # print the list, but we never get here
7 <@> leave[1 ref] vKP/REFC
-e syntax OK
So as you can see, the exit
builtin is run while trying to assemble the argument list for print
. Since exit
causes the program to quit, the print
command never gets to run.
And the last one:
$ perl -MO=Deparse,-p -e 'print ($foo & 255) + 1, "\n";'
((print(($foo & 255)) + 1), '???'); # '???' means this was optimized away
-e syntax OK
$ perl -MO=Concise,-exec -e 'print ($foo & 255) + 1, "\n";'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark v
4 <0> pushmark s
5 <#> gvsv[*foo] s
6 <$> const[IV 255] s
7 <2> bit_and[t2] sK
8 <@> print sK
9 <$> const[IV 1] s
a <2> add[t3] vK/2
b <@> list vK
c <@> leave[1 ref] vKP/REFC
-e syntax OK
sort
is evaluated when it's called, it really doesn't have anything to do with the assignment.sort
returns a list. So what you're assigning is:@ary = (1, 3, (2,4) );
Perl ignores the second parenthesis so you end up with 1,3,2,4
as you would expect.
The comma you're referring to no longer exists. It's the second argument to sort. Perl sees your list as a 3 item list not a 4 item list (it expands it to 4 in the assignment)
rightward does something with the parameters (e.g. prints them out or storing them), leftward does something TO the parameters, usually by modifying them in someway.
print
acts like any other function in Perl (or any other language I've ever used for that matter). If you call a function as an argument, the return value of that function is given as the argument. So your case of:
print ($foo, exit);
or equivalent (the parens don't matter)
print $foo, exit;
does nothing, because you're asking it to print the return value of exit. Your program exits first so you get nothing back. I don't understand why you'd expect exit
to be treated as a string. exit
is a function in all contexts unless you quoted it.
print ($foo & 255) + 1,"\n";
From perlop
which gives this example:
probably doesn't do what you expect at first glance. The parentheses enclose the argument list for "print" which is evaluated (printing the result of "$foo & 255"). Then one is added to the return value of "print" (usually 1). The result is something like this:
1 + 1, "\n"; # Obviously not what you meant.
To do what you meant properly, you must write:
print(($foo & 255) + 1, "\n");
Not sure if what follows is perfectly accurate (it's a mishmash from IRC, the above mentioned answers, google and my interpretation of the book)
(operator)(operands) this is viewed as a leftward operator because it's to the left of the operands. (operands)(operator) this is viewed as a rightward operator because it's to the right of the operands. So, (1, 2, 3, sort 4, 5, sort 6, 7) Here the second sort, acts as both a leftword and a rightword operator!! sort 6,7 is leftword as in to the left of (6,7) - it's operands. It's also to the right of sort(4, 5 so here it's rightward and of very low precedence.
2.
@ary = (1, 3, sort 4, 2); print @ary;
here, sort is a leftward list operator so straight away it's precedence is highest and as 'Cfreak' says..
- print($foo, exit); print $foo, exit;
Here, print is leftward list so highest precedence and so it should execute first BUT! to execute it should resolve it's arguments and the bareword 'exit'. To resolve it, I guess it runs exit, ergo.. Print $foo,... will gobble up all it's arguments then it has to processes them and at the bareword runs it..
- print ($foo & 255) same as above. print gets highest precedence but it needs to now resolve its various arguments.. so $foo & 255 etc as 'Cfreak' explained.
Many thanks guys!
精彩评论