http://qs321.pair.com?node_id=165900


in reply to Variations on substr (2)

Very nice effect! I just had to take a stab at this one... and here it is:

Disclaimer: I might be using the terminology for references and/or typeglobs wrongly here, please correct me if that is the case.

First, some reformatting:

$|++; $.="Just another Perl hacker "; while(!select $',$&,$`,1/200) { (*_,*") = \(substr($.,0,1), substr$.,1,$,++%24); print+qq'\r$"'; $. .= chop }
Then it is time to disect. :)
$|++;
Just turns off buffering.
while(!select $',$&,$`,1/200)
Is just the same thing as:
while(!select undef,undef,undef,1/200)
simply creating an infinite loop with a delay of 0.005 seconds.

  (*_,*") = \(substr($.,0,1), substr$.,1,$,++%24);
takes a reference the first letter of $. (notice the backslash) and puts it into $_ (via the *_ typeglob), while

  (*_,*") = \(substr($.,0,1), substr$.,1,$,++%27);
takes (a reference to) letters 1 to ($, % 27) and puts it into $" (again, via typeglob). It also increases $, everytime, so this expression will go from 0 to 26 and then around again. Compare for(0..26). Also note how I colored the paranthesis, for clarity.
print+qq'\r$"'
prints a carriage return, which puts us back to the start of the line, and then prints the contents of $", which was set on the line above.
$. .= chop
then simply chops the last (and only) character from $_ and puts it first in $. - remember that $_ was made a reference to the first letter in $., so what happens is that the first letter is what is actually chomped. This causes the string in $. to rotate.

So, essentially, we have one loop that rotates "Just another Perl hacker" around, and then an inner loop of sorts, that prints a part of it. The effect is given by the fact that the first character of output is overwritten everytime, while subsequent characters are written much more rarely. We could even rewrite it to the more readable(??):

while(1) { for(0..26) { # go back to start of line print "\r"; # print substring of current $. # using our iterating $_ print substr($.,1,$_); # rotate $. putting first character last $. .= substr($.,0,1,''); # Pause for 0.005 seconds select undef,undef,undef,1/200 } }
to get the same effect...

This was a very nice effect, I must say. I had no idea you could reference a part of a substring that way. Well, you learn something new every day. Thanks for the amusement!


You have moved into a dark place.
It is pitch black. You are likely to be eaten by a grue.