in reply to A simple JAPH

perl -MO=Deparse is more informative:
LINE: while (defined($_ = <ARGV>)) { @_ = $_; } sub BEGIN { foreach $_ (%main::) { eval '@{$_}=${@_}'; } } { print "Just another perl hacker.\n" unless eval "@_"; }
The message
Can't locate Term/ReadLine.pm in @INC (@INC contains: )
occurs because the BEGIN subroutine clobbers every global array variable including @INC. Clobbering @ARGV causes the while loop not to open any files (although as often as not I get the message Can't open : No such file or directory.). Clobbering @_ ensures that it evaluates as false so that JAPH will be printed.

Replies are listed 'Best First'.
Re^2: A simple JAPH
by Dedalus (Scribe) on Mar 10, 2005 at 22:07 UTC
    No, that is not how it works.
    Or at least not how it should, I don't get that can't open message, and indeed one should not get that.
    I'm using ActiveState 5.8.4, but this should not make a difference as the logic is sound (and more cunning than you have so far guessed).
      Hint: clobbered? or assigned?
      I'm using perl, v5.8.1-RC3 built for darwin-thread-multi-2level, and sometimes the variables do get clobbered (rather than assigned). The explanation you're looking for is that
      each array variable is assigned the value ${@_}. BEGIN is called with no arguments, so @_ is empty. ${@_} puts @_ in scalar context so @_ evaluates to the number of its elements, which is 0.

      So each array variable is being assigned the value of $0 which is the name of the source file. The while loop reads each line of the source file and sets @_ to the array consisting of that line. At the end of the loop @_ contains only the last line of the file, which evals to 1 and prints the JAPH message as a side effect. The second half of the || should never be executed.

      The problem with this explanation is that the order of the variables in %:: is not fixed. Once you set @_ to $0 it is no longer empty, so any subsequent assignments are taken from $1 which is undefined. I've extended your code to print the assignments it's making as they happen:
      LINE: while ( defined( $_ = <ARGV> ) ) { @_ = $_; } sub BEGIN { foreach $_ (%main::) { print "\@{$_}='${@_}'\n"; eval '@{$_}=${@_}'; } } { print "Just another perl hacker.\n" unless eval "@_"; }
      I realize this messes up your carefully-designed layout, but eval "}\n" seems to evaluate to a false value, so it still prints the JAPH message. Here's partial output from one less-successful run:
      @{STDIN}='dedalus.pl.tdy' @{*main::STDIN}='dedalus.pl.tdy' ... @{_}='dedalus.pl.tdy' @{*main::_}='' ... @{ARGV}='' @{*main::ARGV}='' ... Can't open : No such file or directory at dedalus.pl.tdy line 1. Just another perl hacker.
      The following modification of your code seems to work reliably here:
      #! /usr/bin/perl -n @_=$_}BEGIN{eval'@{$_}=${@_}'for sort keys%::}{eval"@_"|| print "Just another perl hacker.\n"