Re: Why does assignment change the result?
by jdporter (Paladin) on May 23, 2007 at 18:48 UTC
|
I think what demerphq said could use some clarification.
You are calling the two subs in scalar context, due to the fact that
the results are being immediately subjected to the dot operator (string
concatenation). So you need to understand what the return expression (or, lacking
that, the last expression evaluated) in
each sub will do when evaluated in scalar context.
@_ in scalar context results in the length of the array, which in this
case is the integer 2. It doesn't even matter what the contents of the array
are.
@_[0,1] in scalar context results in the last value in that list.
This is because @_[0,1] is a list expression, not an array. And all lists,
or listy things, evaluate to their last value when in scalar context.
In this case, that value is the string 'two'.
You should try altering your little program to call those subs in list context,
to see what happens. (It's probably what you expected in the first place.)
The easiest and best way to do this is to replace those dots with commas, like so:
print "two easy: ", two_easy( 'one', 'two' ), "\n";
print "two hard: ", two_hard( 'one', 'two' ), "\n";
Remember that print takes an unlimited list of arguments, and they're
all evaluated in list context. (But the dot operator has higher precedence than
the comma.)
A word spoken in Mind will reach its own level, in the objective world, by its own weight
| [reply] [d/l] [select] |
Re: Why does assignment change the result?
by demerphq (Chancellor) on May 23, 2007 at 18:21 UTC
|
If you pass in more than two args or change the assignment from being what is essentially a no-op (such as passing in a tied value) youll see the two are quite different. One returns an array and the other a list. A list in scalar context is its rightmost element, an array in scalar context is its size. Additionally @_ is special, assigning to it alters the original variables passed in. Im actualy surprised you dont get an attempt to modify a read only value error from two_hard().
---
$world=~s/war/peace/g
| [reply] |
|
Additionally @_ is special, assigning to it alters the original variables passed in.
No, it doesn't. Assignment to elements of @_ will change those variables; assignment to @_ replaces its contents entirely.
Isn't Perl wonderful? :-)
Update: IOW, what suaveant said.
| [reply] |
|
I am not positive but I think by assigning to @_ wholesale he is replacing the aliases, not writing to them.
- Ant
- Some of my
best work - (1 2 3)
| [reply] |
|
| [reply] |
|
|
print scalar(()=eval { wantarray ? qw/foo bar baz/ : 1 });
(This prints 3 of course.) | [reply] [d/l] [select] |
|
| [reply] |
|
|
I'm baffled by this too. How can it print 3 when there never is an array? Or is there? (I only see an empty list assigned to, which is not an array, right?)
| [reply] |
|
|
print "two easy: " . two_easy( 'one', 'two', 'three' ) . "\n";
print "two hard: " . two_hard( 'one', 'two', 'three' ) . "\n";
I don't understand what you mean about passing in a tied value. | [reply] [d/l] |
|
To paraphrase what demerphq said :
- Your "two_hard" sub returns an array (@_).
- Your "print" statement uses the concat "." operator, which makes the usage of the return value in a scalar context
- In a scalar context, an array evaluates to the number of elements (2)
Similarly, your "two_easy" sub returns a LIST. (Because you picked out elements of the array, using an array slice).
In a scalar context, a list evaluates to the last element.
For now, you can ignore the "tied" comment.
Update: jdporter is apparently a faster typist than I am. His post essentially says the same thing.
"An undefined problem has an infinite number of solutions." - Robert A. Humphrey
"If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman
| [reply] |
Re: Why does assignment change the result?
by Anonymous Monk on May 24, 2007 at 03:15 UTC
|
This is one of the biggest issue with Perl. @_ is a reference, and change its value will be seen in the calling func.
Any one didn't catch that at the very beginning is not a true saint.
| [reply] |
|
| [reply] |
|
I wanted to understand what was happening, what affected the caller and what didn't so I put a short script together. I may have missed ways to get at @_ and I would be interested if any omissions were pointed out.
The output produced is
At initialisation
Contents are 1 2
In assignTo - assign to @_
Contents now 1 2
In listArgs - list of lexicals
Contents now 1 2
In loopOver - loop over @_
Contents now 2 3
In refTo - take reference to @_ elements
Contents now 3 4
In shiftArgs - lexicals via shift
Contents now 3 4
In useDirect - increment elements directly
Contents now 4 5
A very interesting topic that has cleared up some misunderstandings. Cheers, JohnGG | [reply] [d/l] [select] |
|
|