Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Question about eval

by tiny_tim (Sexton)
on Jan 16, 2007 at 06:30 UTC ( [id://594860]=perlquestion: print w/replies, xml ) Need Help??

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

I am still getting used to Perl. I am wondering about the eval function. At what point of processing the script does an eval function get parsed ? Is it not compile time ? Or is it run time ? I don't even know. Also, why does
if(require "module/that/does/not/exist") { print "loaded module ok\n"; }else{ print "could not load module $@\n"; }
not work ?

Does require not return anything ? Because if I do
eval { require "module/that/does/not/exist"; }
nothing happens ? Do I have to check $@ after eval ? Do i have to check if $@ is defined after every eval call ?

Also, why does this small print statement not generate error ?
print petrol "hello there !";
And why does
eval { print petrol "hi"; }
get executed ok also ???? Please advise. What are some every day uses of eval, which are actually usefull ?

Replies are listed 'Best First'.
Re: Question about eval
by imp (Priest) on Jan 16, 2007 at 07:16 UTC
    require actually requires the file/module, so an error is raised when the file does not exist. You should wrap the require in an eval block (or expression). When using eval it is usually better to have the last statement within the eval always return true, and use that instead of $@ when testing for success. e.g. if (eval "something; 1;") {}

    eval and require:

    if(eval { require "foo.pm"; 1; } ) { print "loaded module ok\n"; }else{ print "could not load module $@\n"; }
    eval and use:
    if(eval " use foo; 1" ) { print "loaded module ok\n"; }else{ print "could not load module $@\n"; }
    As for this line:
    print petrol "hello there !";
    The reason why that does not generate an error is that the first argument to print can be a bareword, which is interpreted as a filehandle name. e.g.:
    print STDOUT "hello\n";
    If you use strict and warnings (which you always should) then you will receive this error:
    Unquoted string "petrol" may clash with future reserved word at p line + 3. Name "main::petrol" used only once: possible typo at p line 3. print() on unopened filehandle petrol at p line 3.
Re: Question about eval
by sgifford (Prior) on Jan 16, 2007 at 07:18 UTC
    At what point of processing the script does an eval function get parsed ? Is it not compile time ? Or is it run time ?
    There are two types of eval which behave quite differently:  eval STRING and eval BLOCK. If eval is passed a string parameter, it is parsed and compiled at runtime; if it is passed an unquoted block of code, it is parsed and compiled at compile-time.
    Also, why does
    if(require "module/that/does/not/exist") { print "loaded module ok\n"; }else{ print "could not load module $@\n"; }
    not work ?
    require dies if it can't find the file it's looking for, rather than simply returning an error. require is a sort of assertion, and if it fails it's considered too severe to keep on running.
    if I do
    eval { require "module/that/does/not/exist"; }
    nothing happens ? Do I have to check $@ after eval ? Do i have to check if $@ is defined after every eval call ?
    Yes, you have to check $@ after every eval to see if anything in the eval failed.
    Also, why does this small print statement not generate error ?
    print petrol "hello there !";
    If you run perl without warnings and strict, undeclared variables simply spring into existence. In this case, petrol is created the first time you use it. It doesn't go anywhere, so output to it is simply discarded. If you add:
    use warnings; use strict;
    to the top of your Perl code, you'll get an error if you try to do this. I recommend starting off all of your scripts that way.
Re: Question about eval
by shigetsu (Hermit) on Jan 16, 2007 at 06:59 UTC
    You might want to read about eval.

    eval is sometimes used to probe loading of modules and act accordingly when loading fails by examining $@.

    eval { require Foo::Bar }; die $@ if $@;

    is "functionally" almost equal to

    use Foo::Bar;

    If you read carefully through the documentation, you'll see there are many other interesting use cases for eval. You should also give Super Search a try since others have already provided useful insight.

Re: Question about eval
by DrHyde (Prior) on Jan 16, 2007 at 10:24 UTC
    Lots of people have told you lots of useful things. But they're all details. I recommend that you go and buy a copy of "Learning Perl" (aka the Llama book). Once you've understood it, go and buy a copy of "Programming Perl" (the camel book). All will become clear.
Re: Question about eval
by jesuashok (Curate) on Jan 16, 2007 at 07:08 UTC
      Care to explain the print petrol "hi\n"; no error question ? I don't understand. Show me some examples please jesuashok.
        If you enable warnings and strict the following is displayed:
        Unquoted string "petrol" may clash with future reserved word at ./blah +.pl line 5. Name "main::petrol" used only once: possible typo at ./blah.pl line 5. print() on unopened filehandle petrol at ./blah.pl line 5.


        Cheers,
        s;;5776?12321=10609$d=9409:12100$xx;;s;(\d*);push @_,$1;eg;map{print chr(sqrt($_))."\n"} @_;
Re: Question about eval
by tiny_tim (Sexton) on Jan 16, 2007 at 07:39 UTC
    Thank you for the replies. It is beginning to make sense, but why does perl allow me to hand a print statement a junk token if I do not use strict ? Also, can I please get a few more uses of eval ? I am still not 100% on eval. Thank you all :)
      Because of TIMTOWDI (there's more than one way to do it). Attempting to print something somewhere is perfectly fine, even on a closed filehandle. But then, you should check the return value of print as it tells you wether the print actually succeeded. If you "use warnings" perl will warn you:
      use warnings; my $junkprint = print JUNK "foo"; my $stdoutprint = print STDOUT "junkprint = '$junkprint'\n"; print "stdoutprint = '$stdoutprint'\n"; __END__ Name "main::JUNK" used only once: possible typo at - line 2. print() on unopened filehandle JUNK at - line 2. Use of uninitialized value in concatenation (.) or string at - line 3. junkprint = '' stdoutprint = '1'

      Read the eval, do, require and use entries in perlfunc, as well as perlfaq8 which contains the difference between do, require and use. Then there is Super Search.

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      why does perl allow me to hand a print statement a junk token if I do not use strict ?

      It's a filehandle, not a junk token. There's no way at compile time to know whether the filehandle has been opened or not, so STDOUT, FH, petrol, $fh are all the same and all perfectly valid.

      I am still not 100% on eval.

      require either returns true, or throws an exception. eval catches exceptions. You can check if an exception has been caught or not by checking $@.

      eval returns undef if an exception has been caught, so you can also do something like

      if (eval { require "module/that/does/not/exist"; 1 } ) { print "loaded module ok\n"; } else { print "could not load module: $@\n"; }

      or since require always returns true,

      if (eval { require "module/that/does/not/exist" } ) { print "loaded module ok\n"; } else { print "could not load module: $@\n"; }
      It's a filehandle, not a junk token. There's no way at compile time to know whether the filehandle has been opened or not, so STDOUT, FH, petrol, $fh are all the same and all perfectly valid.
      This was hinted at in a couple of the above replies, but combined with die (or croak) perl's eval provides a handy way to implement simple exception handling similar to the try/catch of other languages like Java and JavaScript.
      # some code that might fail eval { open MYFILE, "> some_file.txt" or die $!; ... close MYFILE; }; # catch the "exception" if ($@) { print "Errors during file operation: $@\n"; }
      For more, search for "exception" on CPAN; there are several modules that provide more elaborate exception handling mechanisms.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://594860]
Approved by davido
Front-paged by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (5)
As of 2024-05-29 08:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found