Re: print list, comma not working?
by Fletch (Bishop) on Jan 12, 2010 at 16:01 UTC
|
perl -MO=Deparse,-p,-q -e 'my $i=0;for (1..456) {print (($i%100)?"":"
+\n\t"),(($i%10)?".":(int(($i%100)/10)));$i++;};print "\n";'
(my $i = 0);
foreach $_ (1 .. 456) {
(print((($i % 100) ? '' : "\n\t")), (($i % 10) ? '???' : int((($i
+% 100) / 10))));
(++$i);
}
print("\n");
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] [d/l] |
Re: print list, comma not working?
by ikegami (Patriarch) on Jan 12, 2010 at 16:06 UTC
|
print(EXPR), EXPR
is pretty much the same thing as
print(EXPR); EXPR
in void context. You're missing a set of parens.
Had you checked, you would have gotten a "useless use in void context" warning. | [reply] [d/l] [select] |
|
|
Thanks everyone for your feedback/hints. Yes, had I simply added the -w warnings switch I would have gotten feedback from the perl interpreter directly. I guess I was so brain-locked by such a simple problem that I assumed that warnings (and perltidy) wouldn't offer more insight. My mistake.
At this point I guess I would humbly state my opinion that in this instance there perl interpreter has gone beyond TIMTOWTDI to "Thats just plain wrong" (just my opinion).
In my mind, order-of-operation precedence is implicitly bounded by the end-of-statement semi-colon ';'. If a function (like print) takes an argument of LIST, it should greedily operate on all list elements up to the end of the statement indicated by the ';'.
So, "print (LIST),LIST;" should just do "print (LIST,LIST);". I understand that using parens as function argument delimiters is optional, and that inconsistent use of parens with functions leads to ambiguous dilemmas, but if someone really wanted to execute the second list in "function (LIST),LIST;", then they should have not used comma ',' as a statement separator, they should have use a semi-colon as "function (LIST);LIST;".
In my mind, the semi-colon is a statement separator, and the comma is a LIST argument separator. When perl interprets "function (LIST),LIST;" as "function (LIST);LIST;", it is implicitly treating (and converting) the comma into a statement separator.
I really like perl, but in this one instance I think the behaviour is wrong. I am sure that Larry and some other developers have had some philosophical discussions about this example, and if anyone can dig them up I would be happy to read them.
Thanks,
| [reply] |
|
|
You incorrectly assume that the list operator is only used in void context when that's rarely the case. You're advocating that
foo(bar('x'), 'y');
should mean
foo(bar('x', 'y'));
Needless to say, I disagree.
In Perl6, whitespace between the function name and the parens will cause the parens to be treated as part of the argument, not part of the function call.
It's rather impossible to change that in Perl5, assuming it's ever desirable. If you're going to omit the parens around a function call, expect problems. But if you make sure that the first argument doesn't start with a paren, you'll avoid most of them.
| [reply] [d/l] [select] |
|
|
|
|
When perl interprets "function (LIST),LIST;" as "function (LIST);LIST;", it is implicitly treating (and converting) the comma into a statement separator.
You're missing something: precedence. The comma already is a term separator. (Expressions can be terms.) Parentheses group terms to disambiguate the intended precedence.
If you were to change the behavior of parentheses in this case, you'd find all sorts of inconsistencies with how Perl behaves in other cases.
| [reply] |
|
|
| [reply] |
|
|
Re: print list, comma not working?
by Anonymous Monk on Jan 12, 2010 at 16:04 UTC
|
( my $i = 0 );
foreach $_ ( 1 .. 456 ) {
(
print( ( ( $i % 100 ) ? '' : "\n\t" ) ),
( ( $i % 10 ) ? '???' : int( ( ( $i % 100 ) / 10 ) ) )
);
( ++$i );
}
print("\n");
Notice the parens around print, its essentially like
$ perl -le"print(1),2"
1
2nd part
( my $i = 0 );
foreach $_ ( 1 .. 456 ) {
print( ( ( $i % 100 ) ? '' : "\n\t" ) );
print( ( ( $i % 10 ) ? '.' : int( ( ( $i % 100 ) / 10 ) ) ) );
( ++$i );
}
print("\n");
| [reply] [d/l] [select] |
Re: print list, comma not working?
by lostjimmy (Chaplain) on Jan 12, 2010 at 16:06 UTC
|
I believe the problem has to do with your use of parentheses. Perl is parsing it differently from the way your brain is. With the statement print (($i%100)?"":"\n\t"),(($i%10)?".":(int(($i%100)/10)));, you actually have print( ($i%100)?"":"\n\t" ), and then a ternary operator in void context after the comma.
The outer set of parentheses is actually wrapping the arguments of your print statement, so what you think is the second argument to print is actually doing nothing.
To fix it, you need to enclose both elements of the list in another set of parentheses: print( (($i%100)?"":"\n\t"), (($i%10)?".":(int(($i%100)/10))) );
| [reply] [d/l] [select] |
Re: print list, comma not working?
by keszler (Priest) on Jan 12, 2010 at 19:11 UTC
|
Sidestepping the whole parens and list-op discussion, why not just avoid the empty term in $i%100:
perl -e '
my $i=0;
for (1..456) {
print $i%100 ? $i%10 ? "."
: int(($i%100)/10)
: "\n\t";
$i++;
}
print "\n";
'
| [reply] [d/l] |
|
|
That looks good also. I can add a '0' with the "\n\t" to make it print 100 per line. Thanks.
I had tried something like this earlier, but I may have run into more white-space/precedence problems and confusion, so I started adding parens and just fell into another trap.
Will 'use warnings;' in the future.
| [reply] |