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

OK, newbies! It's time for the first installment of the PerlMonks.org Brain Teaser.Click For some background on these "Brain Teasers". A reminder to all you Perl gurus out there, this is for newbies only! If you can come up with the answer without having to think very hard, please don't bother with this. If you learn something from this exercise, though, feel free to vote this node up.

The code below is designed to give you some practice with conditional statements. What do you predict will be output by this code? You can reveal the answer on the "replies" page. How this code works will be posted soon so be sure to bookmark this node.

I expected:
1
2
3
4
5Update:I understand what is going on now. Thanks for the clarification kundra.

Another Update:I just want to make sure that I understand this. In the "foreach" loop $each is assigned a reference to a scalar value in @list. So when $each is modified in the loop what is actually being modified is $list[$i] which happens to be same value as $newlist[$i]. Right?

And maybe in the future it would be a good idea for the
reason for what happens to be included in the 'black box
of enlightenment' so that people won't just be puzzled,
but will learn, too? (Or maybe not; it's good debugging
practice to figure out where the unexpected happens.
Why have the box at all? There isn't much point to just
show the output, since people can just run the
program to see the output.)

Thanks for the feedback. I was debating whether or not to post the solution or some kind of hint along with the answer. I'll try some different things in the future and see what seems to be the most helpful to people. For this one, I plan on posting the answer tomorrow.

I think if people can immediately check the answer and see that their first instinct was wrong, this will tend to get them involved more and make them curious...I think they'll start wondering where they went wrong and figure it out for themselves.

Why the black box? Just for aesthetic reasons...makes it a little more fun, I think.

kudra said:
And maybe in the future it would be a good idea for the reason for what happens to be included in the 'black box of enlightenment' so that people won't just be puzzled, but will learn, too?

First of all: ++ nysus and kudra for promoting learningSince nobody posted the reason why it does this I figured I'd do so. In fact, instead of waste my time, I just took this from "Learning Perl" written by Randal Schwartz, Published by OReilly Associates.

If the list you are iterating over is made of real variables rather than some function returning a list value, then the variable being used for iteration is in fact an alias for each variable in the
list instead of being merely a copy of the values. It means that if you change the scalar variable, you are also changing that particular element in the list that the variable is standing in for.
For example:

From Programming Perl: Note that the loop variable becomes a reference to the element itself, rather than a copy of the element. Hence, modifying the loop variable will modify the original
array.

The snippet loops through the contents of @list and as each cell gets looked at, it is assigned to $each. $each is then modified by multiplying by 2. Modifying $each, modifies the value in the shell, due to the way foreach is constructed in perl. I believe that is all correct. If I have made any mistakes ( other than grammar, and spelling ), someone please tell me.

Now that the cat's out of the bag, I'll share the explanation I had written up...a bit more long winded:

HOW THE CODE WORKS

So what's going on here? At first glance, this bit of code seems pretty straightforward. Line 1 assigns numbers 1 thru 5 to the first 5 elements of the @list array. Lines 3-6 do nothing but declare variables. The foreach loop starting on line 8 assigns each element of @list to $each and multiplies the contents of $each by two. It then assigns each $each to an element of the @newlist array. Finally, the for loop starting on line 14 simply steps through each element of both the @newlist and @list arrays simultaneously and subtracts one array from the other. You would expect the first iteration of the for loop to be 2-1 yielding "1", the next iteration to give 4-2 yielding "2", and so on. So what's the problem here?

The answer lies in the first statement of the foreach block, $each *= 2;. What happens is that the @list array gets aliased through the $each variable. What does this mean? It means that whatever you do to the $each variable in the foreach loop, you also do to the corresponding element of the @list array. So, for example, when $each is equals "3" and it gets multiplied by "2", the third element of @list gets multiplied by "2", too, setting it's value to "6". And there you have the reason why the output of this code is nothing but 5 zeroes!

Alright, I also expected a return of 1,2,3,4, and 5 as the values printed out. However, I think I have learned where I went wrong. I just wanted to make sure I understood the last paragraph of HOW THE CODE WORKS.

If I understand this correctly, the $each variable actually acts as a reference to the current place in the array that the foreach loop is currently at. So in effect we are actually altering the first array with the $each *= 2; and then simply setting the $i place in the @newlist to be the same value. This is the reason why we are subtracting, in the last loop, the exact same values from each other.

Yes, although I do not know if "referencing" is the accurate term. As the post above mine pointed out, the book "Learning Perl" uses the term alias. How that is different from referencing, I'm not entirely certain and maybe a more monkish Monk than I could answer that.

I think that the points about printing an explanation for the results are valid, but I would recommend taking it a step further. Since these teasers have a non-obvious result, I think people would also like to see code that does give the answer that was originally expected. In this case, for instance, how to modify the code so that it prints "1 2 3 4 5". After all, I'm sure we've all experienced the frustration of bugs in our logic; for a newbie the frustration would be worse.

Spacewarp

DISCLAIMER:
Use of this advanced computing technology does not imply an endorsement
of Western industrial civilization.

When putting a smiley right before a closing parenthesis, do you:

Use two parentheses: (Like this: :) )
Use one parenthesis: (Like this: :)
Reverse direction of the smiley: (Like this: (: )
Use angle/square brackets instead of parentheses
Use C-style commenting to set the smiley off from the closing parenthesis
Make the smiley a dunce: (:>
I disapprove of emoticons
Other