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

Hi

I have the feeling of reinventing the wheel and would like to see other solutions...

I'm evaling code text which is composed of 2 snippets which are supposed to be correct in isolation.

Take as example using B::Deparse to back engineer a functions code and then wrapping new code around it before evaling. (something like this is shown in the Perl Hacks book)

Now this additional code could contain new symbols (identifiers) like variables, subnames or labels which might shadow equally named symbols in the original code.

This is known as Hygiene Problem.

I decided to solve this with a template system where new symbols need to be placeholders, which are renamed (extended with a suffix) if they conflict with old symbols.

Did anybody already try to solve this on CPAN?

I'd like to compare different approaches.

Cheers Rolf

(addicted to the Perl Programming Language and ☆☆☆☆ :)

  • Comment on Hygienic eval of templates with perl code?

Replies are listed 'Best First'.
Re: Hygienic eval of templates with perl code?
by Arunbear (Prior) on Aug 27, 2014 at 11:31 UTC
    Eval::Closure is designed to help with eval'ing functions out of text.
      Thanks, interesting module, I will learn a lot.¹

      (I think I subconsciously had this in mind =)

      But it doesn't seem to address the hygiene problem.

      As an illustration by extending the synopsis (untested)

      sub wrap { my ($old_body, $environment) = @_; my $new_body = <<'__WRAP__'; #---PRE_BODY my $foo++; # new var #<OLD_BODY># #--- POST_BODY print $foo; __WRAP__ $new_body =~ s/#<OLD_BODY>#/$old_body/g; my $code = eval_closure( source => "sub { $new_body }", environment => $environment, ); }

      Now the problem starts if $foo is part of the closure environment.

      I tried to solve this by using placeholders like $<FOO> in the wrapped code.

      This translates (regex) to $_FOO_ iff $_FOO_ is not already part of the environment.

      Otherwise it translates to something like $_FOO_A .

      (the suffix is incremented till there is no conflict)

      Other strategies (gensym, obfuscation, packages) are listed in the WP article, but I wanted to have a notation with readable symbols in the debugger.

      I hope it's clearer now.

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

      ¹) especially how the use of PadWalker was avoided?

        Wouldn't a package give you readable symbols? e.g.
        $Some::Package::foo++; # new var
        instead of
        my $foo++; # new var
        You could also choose a package name in such a way as to reduce the chance of a collision.