Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

source filters in eval

by powerman (Friar)
on Feb 24, 2003 at 23:21 UTC ( #238288=perlquestion: print w/replies, xml ) Need Help??
powerman has asked for the wisdom of the Perl Monks concerning the following question:

Is it possible to realize this in straight way?
Is it possible to redefine 'eval'?
Is it correct to use '::eval' instead of '&eval()'?
Any pitfalls?
#!/usr/bin/perl require 5.8.0; package filter; use Filter::Simple; FILTER { s/\bHi\b/Hello/g }; package main; BEGIN { $INC{''} = $0 } use Data::Dumper; sub eval ($) { open my $FH, '<', \$_[0]; local @INC = (sub {shift @INC; $FH}, @INC); do 'filtered :-)'; }; $code = "use filter;\nprint 'Hi from eval!\n';die 'test'"; # filtered eval $ret = ::eval $code; print 'ret=',Dumper($ret),'err=',Dumper($@); # not filtered eval $ret = eval $code; print 'ret=',Dumper($ret),'err=',Dumper($@);

Replies are listed 'Best First'.
Re: source filters in eval
by djantzen (Priest) on Feb 25, 2003 at 01:08 UTC

    For the sake of clarity, I would name it something entirely different from CORE::eval. But using '::' to indicate the version found in the current package is preferable to '&' so that you avoid '@_' being passed unmodified from the calling context to the scope of the subroutine. In general, '&' should only preface subroutine calls in very specific and peculiar circumstances.

    That said, I'm wondering if you're planning to use this for some kind of code vetting, rather than the simple substitution in your example code? If so, then take a look at Safe and Opcode.

    Update: ihb is correct.

    "The dead do not recognize context" -- Kai, Lexx
      But using '::' to indicate the version found in the current package ...

      The :: doesn't indicate the subroutine is found in the current package. On the contrary. It clearly (?) specifies which package the subroutine is found in, and that's main.

      ... is preferable to '&' so that you avoid '@_' being passed unmodified from the calling context to the scope of the subroutine

      Using & doesn't necessarily mean @_ gets passed. That only happens if there is no parenthesis. If you look at the OP, you'll see that it asks about &eval(). And looking at the prototype of &eval makes it clear that it always is supposed to be called with one argument, so the behaviour you speak of is quite unlikely to happen.

      So, using :: is not preferable to &. The only advantage is that it still honours prototypes, but the downside is that you package qualify the subroutine so when you move it you'll have to rename all calls to it. The real fix, as you say, is to not name it "eval".

      Maybe this is not clear indicated reasons of this trick (and re-inventing of eval).
      Problem is indicated in subject of node. E.g. source filters in 'eval' code magically don't work.
      So this is workaround of this problem and this post mean questions :
      - Is this is correct workaround ?
      - Can this be done more simply ?
      - And if it can't, how we can make this work magically ? E.g. if we can override (re-define) CORE::eval

        Isn't that because you used the expression (quoted) form of eval? The code would have already been compiled and (I think) source filters are applied at compile time. What happens if you try a block style eval?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://238288]
Approved by jmcnamara
Discipulus a missing semicolon after use LWP::UserAgent caused very strange behaviour and not the normal warning...
[choroba]: Yes, sometimes missing ; after the use clause just interprets the next line somehow and passes the result to the used module which could happily ignore it. Been there, seen that.

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (6)
As of 2017-02-28 08:43 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (398 votes). Check out past polls.