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

Greetings monks. I've got some code that uses eval and is not behaving the way I'd expect, and I'd like to know if anybody has an idea what might be going on. I've checked the obvious sources (perldoc, the Camel, etc.) but haven't found anything to shed light on this. Here's a pared-down example to illustrate:
use strict; my @items = ('file1', 'file2', 'file3'); open INPUT_FILE,"/no/such/directory/$items[2]" or print eval 'qq{unabl +e to open file $items[2]: $!\n}'; open INPUT_FILE,"/no/such/directory/$items[1]" or print eval 'qq{unabl +e to open file $items[1]: $!\n}'; open INPUT_FILE,"/no/such/directory/$items[0]" or print eval 'qq{unabl +e to open file $items[0]: $!\n}';
The output from this is:
unable to open file file3: unable to open file file2: unable to open file file1: No such file or directory
Before you ask why I'm using eval in such a goofy way: This is just an artificial test case I've created to demonstrate the behavior in distilled way, not how I'm actually writing the code. Anyway, the thing that you can see here is that if the string being evaluated includes an array element with an index other than zero, the value of $! seems to get squashed. I would've expected all three lines of output above to be identical except for filename, since the only difference in the three lines is which array element is included in the string being evaled. I'm using ActivePerl 5.6.0 on Linux and Win2K. Any insight would be appreciated!

Replies are listed 'Best First'.
(jeffa) Re: eval and variable scope
by jeffa (Bishop) on Dec 17, 2001 at 06:47 UTC
    I don't have an answer, but i do have some interesting test results:
    # version 5.006 unable to open file file3: unable to open file file2: unable to open file file1: No such file or directory # version 5.006001 unable to open file file3: unable to open file file2: unable to open file file1: No such file or directory # version 5.007002 unable to open file file3: No such file or directory unable to open file file2: No such file or directory unable to open file file1: No such file or directory
    Looks like the only one that didn't 'squash' $! was 5.7.2.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    F--F--F--F--F--F--F--F--
    (the triplet paradiddle)
    
      Thanks, jeffa!

      Since this doesn't seem to behave consistently between different versions of Perl, I'll probably have to adopt a different approach in my code. But at least now I know I'm not going insane ;-)

        I'm stumped as well.... If you're looking for a different approach, you might try replacing eval '...' with do{...}

        I know this is a trimmed down example, but this seems to work for me:

        ... or print do {qq{unable to open file $items[2]: $!\n}};

        -Blake

Re: eval and variable scope
by Zaxo (Archbishop) on Dec 17, 2001 at 06:57 UTC

    Another data point for jeffa's results:

    version 5.00503 unable to open file file3: No such file or directory unable to open file file2: No such file or directory unable to open file file1: No such file or directory

    Update: Fwiw, strace gives the following:

    version 5.6.0 open("/no/such/directory/file3", O_RDONLY|0x8000) = -1 ENOENT (No such + file or directory) brk(0x80fa000) = 0x80fa000 fstat(1, {st_mode=S_IFREG|S_ISUID, st_size=0, ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) += 0x40014000 ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0 write(1, "unable to open file file3: \n", 28) = 28 open("/no/such/directory/file2", O_RDONLY|0x8000) = -1 ENOENT (No such + file or directory) write(1, "unable to open file file2: \n", 28) = 28 open("/no/such/directory/file1", O_RDONLY|0x8000) = -1 ENOENT (No such + file or directory) write(1, "unable to open file file1: No su"..., 53) = 53 SYS_175(0x2, 0xbffff8c4, 0, 0x8, 0x2) = 0 munmap(0x40014000, 4096) = 0 version 5.00503 open("/no/such/directory/file3", O_RDONLY) = -1 ENOENT (No such file o +r directory) open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENO +ENT (No such file or directory) open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT + (No such file or directory) fstat64(0x1, 0xbffff6f0) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, +-1, 0) = 0x40468000 ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0 write(1, "unable to open file file3: No su"..., 53) = 53 open("/no/such/directory/file2", O_RDONLY) = -1 ENOENT (No such file o +r directory) write(1, "unable to open file file2: No su"..., 53) = 53 open("/no/such/directory/file1", O_RDONLY) = -1 ENOENT (No such file o +r directory) write(1, "unable to open file file1: No su"..., 53) = 53 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 munmap(0x40468000, 4096) = 0

    After Compline,
    Zaxo