[Phoenix-pm] Eval Namespace Question

Douglas E. Miles perlguy at earthlink.net
Mon Aug 7 19:42:21 PDT 2006


Scott Walters wrote:

>Hi Doug,
>
>So, what *have* you been up to?
>
>Don't use eval on a string.  eval { } is fine to use and you should be
>trapping errors, and that's how that's done.  99% of the time people use
>eval on a string, they're trying to hammer in a screw.
>
>  
>
I'm evaling a string because that's what I have. :)  I might be 
hammering a screw, but it's been working fine for several years.  I 
wrote the code knowing "Caveat Emptor".  The real code is trapping 
errors.  I just made the smallest example that illustrated the behavior 
I was wondering about.  As far as what I've been up to, unfortunately, 
mostly ASP.  The Perl is cleansing me. :)

>>This means that in my code below, that $bar is in scope within the 
>>eval.  What blows me away is that $foo::foo is also in scope because of 
>>the "package foo" statement in $eval_string.  Does anyone know how perl 
>>
>>#!/usr/bin/perl
>>package foo;
>>    
>>
>
>Use strict and warnings.
>
>  
>
>>$foo = "FOO!";
>>    
>>
>
>  
>
>>package bar;
>>my $bar = "BAR!";
>>my $perl_code = 'print "$bar $foo\n"';
>>print "$perl_code\n";
>>
>>my $eval_string = "package foo;\n$perl_code";
>>eval $eval_string;
>>    
>>
>
>To answer your actual question, variables created (defined implicitly or explicitly)
>at the "top level" (outside of any blocks) have a scope called "file scope", where
>they're in scope until the end of the file.  This would work with my $foo too.
>Sometimes people do this to get less scope than file scope:
>
>package foo; {
>    my $foo = "FOO!";
>}
>
>package bar; {
>  ...
>}
>
>There are other derivitives of out.
>
>Now, here's what you *should* be writing to avoid a plague of security and
>performance problems too numerous to enumerate and too pervasive to ignore
>the shame they've brought upon us all:
>
>package foo;
>use strict;
>use warnings;
>my $foo = "FOO!";
>
>package bar;
># note that strict and warnings also have file scope
>my $bar = "BAR!":
>my $perl_code = sub { print "$bar $foo\n"; };
>$perl_code->(); # note that you could pass arguments
>
>In this adaptation, you can't easily modify the code by prepending things
>like "package foo;", but dataflow is an entire other question.  Rather than
>changing packages that code evaluates in, you should be passing objects in,
>and the object should encapsulate the set of values.  Also, with code references,
>if the code reference references some variable (such as $foo and $bar), if
>the value of $foo or $bar changes (the *same* $foo or $bar, not one 
>created later or in a different scope) then the value that gets printed
>also changes.  
>
>So...
>
>1. use code references instead of eval
>2. use object instances rather than packages full of global values
>3. when you want a global of some sort, use the constant module... use constant foo => 'FOO!';
>4. report to the list more often and tell us how your life is going
>   and what you're up to, for chrissakes!
>
>As far as the "use objects" spiel... I'm assuming the worst, so forgive me for that, but
>in my experience, the not-so-bad-scenario can usually be considered to be similar enough
>to the bad scenario that the refactoring/best practice/design heuristic/whatever
>still applies.  Computing package names on the fly invokes fear and dread for good
>reason and should only be used to intentionally voke fear and dread.  Etc, etc, etc.
>
>Glad to see you're still alive, Doug.
>
>-scott
>
>
>
>  
>
>>_______________________________________________
>>Phoenix-pm mailing list
>>Phoenix-pm at pm.org
>>http://mail.pm.org/mailman/listinfo/phoenix-pm
>>    
>>



More information about the Phoenix-pm mailing list