Oddity with the x and . operators

D

Dan Wilga

I've run into something that has me totally puzzled. If I do this:

print "foo".("." x 5);

as expected, I get:

foo.....

However, if I do:

print ("." x 5)."foo";

I get only:

.....

Why does the "foo" get discarded?

I can get around this by changing the code to:

print scalar("." x 5)."foo"

But, according to perlop, I wouldn't think this should be necessary:

"In scalar context or if the left operand is not enclosed in
parentheses, it returns a string consisting of the left operand repeated
the number of times specified by the right operand."

Shouldn't the use of the '.' operator outside be sufficient to cause the
parenthetical part to be considered a scalar? Even if it's not, and the
bit inside the parens evaluates to a single-element list, I would still
expect to see:

1foo
 
A

Andreas Kahari

Dan Wilga wrote: said:
However, if I do:

print ("." x 5)."foo";

The argument to print is '"." x 5'. The return value from print
is concatenated with the string "foo" and the result is then
thrown away.
 
A

A. Sinan Unur

I've run into something that has me totally puzzled. If I do this:

print "foo".("." x 5);

as expected, I get:

foo.....

However, if I do:

print ("." x 5)."foo";

I get only:

.....

Why does the "foo" get discarded?

print (("." x 5)."foo");
 
G

Glenn Jackman

Dan Wilga said:
I've run into something that has me totally puzzled. If I do this:
print "foo".("." x 5);
as expected, I get:
foo.....

However, if I do:
print ("." x 5)."foo";
I get only:
.....

The left paranthesis is being consumed by the print operator, and the
concatenation operator has lower precedence. The perlop man page says:
If any list operator (print(), etc.) or any unary operator
(chdir(), etc.) is followed by a left parenthesis as the
next token, the operator and arguments within parentheses
are taken to be of highest precedence, just like a normal
function call.

See what perl tells you:
$ perl -we 'print ("." x 5)."foo";'
print (...) interpreted as function at -e line 1.
Useless use of concatenation (.) or string in void context at -e line 1.
.....

To obtain happiness, add more parentheses or use the unary plus operator:
$ perl -we 'print(("." x 5)."foo");'
.....foo
$ perl -we 'print +("." x 5)."foo";'
.....foo
 
D

Darren Dunham

Dan Wilga said:
I've run into something that has me totally puzzled. If I do this:
print "foo".("." x 5);
as expected, I get:

However, if I do:
print ("." x 5)."foo";
I get only:

If you get only that, then you're not using warnings.
Why does the "foo" get discarded?

One of the warnings is...
print (...) interpreted as function at -e line 1.

Perldiag mentions..
%s (...) interpreted as function
(W) You've run afoul of the rule that says that any list
operator followed by parentheses turns into a function,
with all the list operators arguments found inside the
parentheses. See the section on Terms and List
Operators (Leftward) in the perlop manpage.

Which would take you to perlop which explains this in that section.
I can get around this by changing the code to:
print scalar("." x 5)."foo"

Right. You got rid of the leading "(" immediately after the print, so
it's not interpreted as the entire argument to the function. There are
several other rewrites you could do.
Shouldn't the use of the '.' operator outside be sufficient to cause the
parenthetical part to be considered a scalar? Even if it's not, and the
bit inside the parens evaluates to a single-element list, I would still
expect to see:

That's not what the problem is.
 
D

Dan Wilga

Nevermind. I found the answer to my question just a few paragraphs down
in perlop:

"If any list operator (print(), etc.) or any unary operator (chdir(),
etc.) is followed by a left parenthesis as the next token, the operator
and arguments within parentheses are taken to be of highest precedence,
just like a normal function call. Examples:"

There's also a warning in perlfunc:

"Also be careful not to follow the print keyword with a left parenthesis
unless you want the corresponding right parenthesis to terminate the
arguments to the print--interpose a `+' or put parentheses around all
the arguments."

So the code:

print ("." x 5)."foo";

is being evaluated as:

print("." x 5)

and then the return value of the "print" is being concatenated with
"foo" and discarded.

So much of the way Perl works has become intuitive to me after using it
for so long, but this one, I just don't know if I can ever accept it.
(I'm not looking for an argument here, just stating that it seems
unintuitive if you never use the return value from print.)
 
T

Tad McClellan

Dan Wilga said:
I've run into something that has me totally puzzled.


That can happen when you do not enable warnings.

(so you should enable them)

However, if I do:

print ("." x 5)."foo";

I get only:

.....


You should always enable warnings when developing Perl code.

Why does the "foo" get discarded?


It isn't (directly) discarded.

It is concatentated with whatever print() returned (probably a 1)
and the result of the concatenation is then discarded (void context).

I can get around this by changing the code to:

print scalar("." x 5)."foo"


Or to any of these:

print( ("." x 5) . "foo"); # parens around _entire_ arg list

print "." x 5 . "foo";

print +("." x 5) . "foo";

But, according to perlop, I wouldn't think this should be necessary:

"In scalar context or if the left operand is not enclosed in
parentheses, it returns a string consisting of the left operand repeated
the number of times specified by the right operand."


The problem is not related to concatenation, the problem is
related to print() (or _any_ function actually).

Shouldn't the use of the '.' operator outside be sufficient to cause the
parenthetical part to be considered a scalar?


Yes, but not-being-a-scalar is not your problem.

Even if it's not, and the
bit inside the parens evaluates to a single-element list, I would still
expect to see:

1foo


Why would you expect that?

(a list in scalar context does NOT evaluate to the number of
elements in the list. In fact, a list cannot exist in scalar
context at all!)


See this thread for what is really causing your problem (wrapped):

http://groups.google.com/groups?
as_umsgid=slrnatq036.2q2.tadmc%40magna.augustmail.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,362
Latest member
ChandaWagn

Latest Threads

Top