Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-17 Thread Kripa Sundar
Dear Ben, Tim and others,

I've been learning a lot from this entire thread.  Thanks to all the
responders.

Tim writes:

 [...] [W]e can indeed add another item to Kripa's list:
 
 * context confusion
  eval() executes in the context in which it's called, not the
  context in which the code string is assembled. So if these two are
  different, be sure your code is clear about which context the
  eval()'ed code sees. [...]

Thanks for this concise addition to my original list.  It helps me
understand the recent discussion better.

peace, || What can one hour achieve?
--{kr.pA}  || http://www.workanhour.com/
--
Kid, n.: A noise with dirt on it.
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-17 Thread Uri Guttman
 KS == Kripa Sundar [EMAIL PROTECTED] writes:

  KS Dear Ben, Tim and others,
  KS I've been learning a lot from this entire thread.  Thanks to all the
  KS responders.

i just want to reiterate my view on string eval (and symrefs). they are
powerful tools that are needed to solve a certain class of
problems. they rarely are the best solution and must be used only when
they give you a distinct advantage when used. most problems that newbies
think need them, do not. they are dangerous in that data will be
affecting code and that is hard to debug, verify, etc. string eval will
delay any compilation to run time vs compile time so you can lose out on
finding syntax errors until much later. generating code to be evaled is
not easy and it is frought with trickiness. if you code up bad data, you
could unexpectedly affect any global in the system and that is very hard
to track down.

damian's perl best practices has a rule/section on not using string
eval. it isn't as strongly worded as my rule (see below) but it offers
some good reasons, notably the delayed syntax checking point. damian
prefers closures or anon subs if you need to pass in user code.

so my rule again (and kripa, tell your cow-orker this one) is:

you should not use string eval (or symrefs) unless you know when not to
use them. they are not the tool of first resort but a tool of last
resort.

and since i brought up symrefs, i will expound on why they are bad
too. first off, the symbol table is just a specialized hash tree with
different syntax. so doing general purpose data munging in the symtree
is a total waste since you can always do it in normal data trees. and
normal trees offer isolation (you can pass subtrees around and nothing
but that tree will get munged) and lexical scoping for both safety and
garbage collection (lexical trees will get reclaimed with no more refs
point to it, symref trees are global and never collected unless you do
major explicit work). as with string eval, if the data is bad, you can
accidentally refer to distant global vars and that is a nasty bug to
fix. the rule here is that you only use symrefs when you are munging the
symbol table. this is needed with exporting, inserting methods on the
fly (e.g. AUTOLOAD or pregenerating accessors), etc. those are not data
munging but actual symtable munging.

kripa, ask your cow-orker to defend his use of string eval. as in why it
is needed vs solving the problem in some other safer and more
understandable way. ask him if it is faster, easier to understand, makes
cleaner code, safer, etc.

here is one small use of string eval which makes for cleaner code:

if you are loading a module on the fly (its class name is generated or
comes from a config file), then this doesn't work if all you have is
Foo::Bar in $class.

require $class ;

require with an expression needs a path to the module and that means
that :: needs to be converted to the proper separator for the OS
(File::Spec can do that for you) and .pm must be appended as well. so
this would take a few lines of code (which could be wrapped in a sub to
make it cleaner). but it can be done in one clear line with string eval:

eval require $class ;

and check the result and $@ for errors. and put in a comment that you
know what you are doing. :)

uri

-- 
Uri Guttman  --  [EMAIL PROTECTED]   http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs    http://jobs.perl.org
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-17 Thread Kripa Sundar
 i just want to reiterate my view on string eval (and symrefs). they are
 powerful tools that are needed to solve a certain class of
 problems. they rarely are the best solution [...]
 so my rule again (and kripa, tell your cow-orker this one) is:
 
 you should not use string eval (or symrefs) unless you know when not to
 use them. they are not the tool of first resort but a tool of last
 resort.
 [...]

Thanks for the summary, Uri.

peace, || What can one hour achieve?
--{kr.pA}  || http://www.workanhour.com/
--
Kid, n.: A noise with dirt on it.
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-16 Thread Tim King
Ben Tilly wrote:
 I agree that using eval here is wrong. But I still
 don't see action at a distance.
 
 You can argue about whether it is action at a distance, but you
 have tight coupling between the internals of make_generator
 and the string passed into it that was generated from very far
 away.

Correct. A function that uses eval() does so in its own context. I don't 
see what makes this a problem with eval(). Rather, it's a concern that 
affects the software design.

 The problem in this example is that make_generator doesn't make a
 generator.
 
 I know full well what the problem is.  And the result is that you
 cannot consider using code generation for a situation like this.

Not if you want to make a generator as you have tried, no. My point was 
that this is not a problem with eval(); it's a problem with your 
proposed design.

I use eval() when I don't know what the code is until runtime, or to 
execute code generated in one place in a context generated from another. 
But I can't recall a case like the latter that wasn't also an instance 
of the former.

   sub foo {
 my $x = 7;
 my $generator = sub{++$x};
 print $generator-() for 1..5;
   }
 
 But in general you're now
 prevented from adding various kinds of syntactic sugar,
 manipulating the passed in code before compiling it, etc.

If you really need to manipulate the code, you apply the syntactic sugar 
when generating the code string. Then you invoke eval() in whatever 
context the code should execute.

Or alternatively, you can pass to the code-generator an evaluation 
context that the generated code will use. One might use a technique like 
this when using Perl as a scripting language within a Perl program, for 
example.

 Note that $generator... is a true coroutine.
 
 It is not a coroutine.  It is a closure.

It is both a closure and a coroutine.

-TimK
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-16 Thread Ben Tilly
On 8/16/05, Tim King [EMAIL PROTECTED] wrote:
 Ben Tilly wrote:
  I agree that using eval here is wrong. But I still
  don't see action at a distance.
 
  You can argue about whether it is action at a distance, but you
  have tight coupling between the internals of make_generator
  and the string passed into it that was generated from very far
  away.
 
 Correct. A function that uses eval() does so in its own context. I don't
 see what makes this a problem with eval(). Rather, it's a concern that
 affects the software design.

Well this thread started with someone looking for reasons not to use
eval.  Pointing out that certain ways of trying to use eval affect the
software design in negative ways is a good reason to not use eval in
some situations.

  The problem in this example is that make_generator doesn't make a
  generator.
 
  I know full well what the problem is.  And the result is that you
  cannot consider using code generation for a situation like this.
 
 Not if you want to make a generator as you have tried, no. My point was
 that this is not a problem with eval(); it's a problem with your
 proposed design.

You can place the blame wherever you want to.  But with a more
capable version of eval, you can make the proposed design work.

Of course since Perl doesn't *have* capable enough version of
eval, you can't make it work in Perl...

 I use eval() when I don't know what the code is until runtime, or to
 execute code generated in one place in a context generated from another.
 But I can't recall a case like the latter that wasn't also an instance
 of the former.

sub foo {
  my $x = 7;
  my $generator = sub{++$x};
  print $generator-() for 1..5;
}
 
  But in general you're now
  prevented from adding various kinds of syntactic sugar,
  manipulating the passed in code before compiling it, etc.
 
 If you really need to manipulate the code, you apply the syntactic sugar
 when generating the code string. Then you invoke eval() in whatever
 context the code should execute.

The problem is that the place where you'd like to centralize the
code manipulation, calling eval, catching errors etc is in one
place, and the code that you'd like to manipulate is in another.
You *can* achieve the desired flow of control, but the only way
that I can think of doing it in Perl is to require the caller to pass
in sub {eval(shift)} (which will do an eval in the caller's context).
That's an ugly construct to have to throw in when you were
trying to create syntactic sugar.

 Or alternatively, you can pass to the code-generator an evaluation
 context that the generated code will use. One might use a technique like
 this when using Perl as a scripting language within a Perl program, for
 example.

I suspect that you mean something like the sub {eval(shift)} that
I mentioned above.

  Note that $generator... is a true coroutine.
 
  It is not a coroutine.  It is a closure.
 
 It is both a closure and a coroutine.

If it is a coroutine, then you should be able to return multiple times
and restart the call each time.  (Traditionally done with a yield
operator.)

I don't see that capability there...

Cheers,
Ben
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-16 Thread Tim King
Hi, Ben. I began crafting an on-list reply, only to find I had nothing 
substantive to add. Then I began writing a private message, only to 
discover that perhaps this still makes interesting discussion. Now I'm 
thinking we may be on to something here that actually applies directly 
to the original post.

I think we're on the same page practically speaking, but not 
didactically. That is, given a concrete design problem, we'd come to 
similar conclusions; but we're taking opposite approaches.

Kripa was looking for general reasons to avoid eval() or to be careful 
when using eval(). So we start talking about code fragments in which 
eval() doesn't apply. To my mind, that immediately implies a number in 
which it does. Or to put it another way, if I misuse eval(), that's not 
eval()'s fault; it's mine. To my mind, that's no reason to avoid the 
language feature; rather, that's a reason to understand the language 
feature before using it (as one ought any language feature).

To compare, some say we should avoid Perl because it allows us to write 
messy, dense code. Yeah, so? It also allows us to design concise, 
elegant solutions quickly. /But then,/ the argument goes, /no one else 
can understand that code./ Roll-eyes. And by the same token, just 
because you can write code that doesn't work using eval() in ways that 
would confuse someone who doesn't have the perldocs handy, that's a poor 
reason to avoid eval() in general.

 You can place the blame wherever you want to.  But with a more
 capable version of eval, you can make the proposed design work.

To my mind, it's not about blame. Rather, it's about designing elegant 
software that works. And if eval() doesn't do what we want in a given 
situation, we use something that does work.

The greater danger is writing code that works but is fragile. So in that 
sense, maybe we can indeed add another item to Kripa's list:

* context confusion
 eval() executes in the context in which it's called, not the
 context in which the code string is assembled. So if these two are
 different, be sure your code is clear about which context the
 eval()'ed code sees. Otherwise, one might be misled, thinking the
 wrong set of variables are being accessed, and inadvertently
 introduce bugs.


Other stuff:

 The problem is that the place where you'd like to centralize the
 code manipulation, calling eval, catching errors etc is in one
 place, and the code that you'd like to manipulate is in another...

I guess I don't understand the design requirements. It sounds 
potentially like an interesting design challenge. But I think you'd have 
to nail down the requirements a little more.

 Note that $generator...
 It is not a coroutine.

I finally looked it up. You're right. One of these days my mind will 
completely go, and about that time I'll be working on a highly 
classified, mission-critical project for the Defense Department and...

-TimK
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-15 Thread Kripa Sundar
Dear Uri,

Thanks to you and the others for your prompt responses.

 another bad point about eval is that it can access and modify lexicals
 and globals anywhere in the code. so that can lead to action at a
 distance and very hard to find bugs.

I don't quite follow.

Globals are anyway accessible.  How does eval() make things worse?

How can lexicals that are outside the scope of the eval statement be visible?

I made an I-know-I-am-not-doing-what-you-mean attempt, which failed
predictably.

--\/BEGIN-\/--
% perl -wMwarnings -le '{my $x = 10} eval q{print $x;}; eval {print $x;}'
Name main::x used only once: possible typo at -e line 1.
Use of uninitialized value in print at (eval 1) line 1.

Use of uninitialized value in print at -e line 1.

%
--/\-END--/\--

So could you show me examples of naughty access of globals and
locals through eval()?

Your point about eval-BLOCK not being an eval at all is co-incidentally
demonstrated by the above one-liner.  The warning from the eval-STRING
mentions eval.  The warning from the eval-BLOCK does not.

 send a copy of perl best practices to him and watch his eyeballs hit the
 floor when he sees how many other of damian's rules he is breaking. :)

:-)
As soon as you I read the review copy I get from you, I guess.  :-)

peace, || What can one hour achieve?
--{kr.pA}  || http://www.workanhour.com/
--
Kid, n.: A noise with dirt on it.
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-15 Thread Kripa Sundar
Dear Tom,

 You seem to be blending the concepts of eval and system.

Sorry about the confusing presentation there.  My friend had
actually written something like:

--\/BEGIN-\/--
$string = system(\cat $somefile | mail -s \\\$something\\\ $audience\);
eval $string;
--/\-END--/\--

Yeah, including all the backslashes.  :-)

I asked him to re-write it as:

--\/BEGIN-\/--
system(cat $somefile | mail -s '$something' $audience);
--/\-END--/\--

That is why my advice to him included references to system().


 Your comments about doing something that has life beyond the process 
 itself and incomplete run seem a bit muddled and not consistent with 
 how eval behaves. Yes, as another poster pointed out, if you don't check 
 $@ after an eval, an error (compilation or otherwise) can go unnoticed, 
 if that's what you mean.

That is just part of what I meant.  By using an unnecessary
eval-STRING, he is postponing syntax errors to run-time.  So some
detrimental actions may get taken before the syntax error is hit.
Without the eval, the same error would be detected at compile-time, and
the hypothetical actions would not be taken at all.  As they say,
extinction is forever.  Some actions cannot be undone even if you
test for [EMAIL PROTECTED]

You will have seen Uri's response to you about eval-BLOCK.  eval-BLOCK
is not really an eval at all.

peace, || What can one hour achieve?
--{kr.pA}  || http://www.workanhour.com/
--
Kid, n.: A noise with dirt on it.
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-15 Thread Ron Newman

On Aug 15, 2005, at 11:17 AM, Kripa Sundar wrote:
 I asked him to re-write it as:

 system(cat $somefile | mail -s '$something' $audience);

Which of course should really be written as:

system(mail -s '$something' '$audience'  $somefile);

 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-15 Thread Kripa Sundar
 Which of course should really be written as:
 
 system(mail -s '$something' '$audience'  $somefile);

Yes, of course.  It is one of the classic useless uses of cat(1).
I had meant to write this also to my friend, but forgot in my
indignation over six backslashes.  :-)

peace, || What can one hour achieve?
--{kr.pA}  || http://www.workanhour.com/
--
Kid, n.: A noise with dirt on it.
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-15 Thread Kripa Sundar
Dear Ben,

   another bad point about eval is that it can access and modify lexicals
   and globals anywhere in the code. so that can lead to action at a
   distance and very hard to find bugs.
  [...]
 I'm not sure if this is what is referred to, but it applies.
 
 If this is dynamic code where the string to be evaled is
 passed in from elsewhere, then one problem is that you
 might wind up picking up lexicals in the scope of the
 eval, and being unable to pick up lexicals in the scope
 where you tried to create the eval.  Closures would get
 this right.
 
 Ruby solves this problem by giving you a number of
 variations on eval, one of which evals things in the
 context of your caller.  Still not perfectly general, but
 much more likely to be right in this instance.

Do you mean examples like below?

--\/BEGIN-\/--
% perl -le 'my $x = 7; my $str = q{print ++$x}; {my $x = 11; eval $str}'
12
%
--/\-END--/\--

IMHO the current behaviour is intuitive.  And I certainly don't
see action at a distance.  The person who thinks that the '$x' inside
$str is referring to the currently visible $x (value 7) is simply
mistaken.  Likewise the person who thinks that the inner $x will remain
untouched by the eval().  (But maybe this latter is what Uri is
referring to as action at a distance.)

peace, || What can one hour achieve?
--{kr.pA}  || http://www.workanhour.com/
--
Kid, n.: A noise with dirt on it.
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-15 Thread Ben Tilly
On 8/15/05, Kripa Sundar [EMAIL PROTECTED] wrote:
 Dear Ben,
 
another bad point about eval is that it can access and modify lexicals
and globals anywhere in the code. so that can lead to action at a
distance and very hard to find bugs.
   [...]
  I'm not sure if this is what is referred to, but it applies.
 
  If this is dynamic code where the string to be evaled is
  passed in from elsewhere, then one problem is that you
  might wind up picking up lexicals in the scope of the
  eval, and being unable to pick up lexicals in the scope
  where you tried to create the eval.  Closures would get
  this right.
 
  Ruby solves this problem by giving you a number of
  variations on eval, one of which evals things in the
  context of your caller.  Still not perfectly general, but
  much more likely to be right in this instance.
 
 Do you mean examples like below?
 
 --\/BEGIN-\/--
 % perl -le 'my $x = 7; my $str = q{print ++$x}; {my $x = 11; eval $str}'
 12
 %
 --/\-END--/\--

Close, but I meant more like this:

  sub foo {
my $x = 7;
my $generator = make_generator(q{++$x}};
print $generator-() for 1..5;
  }

  sub make_generator {
my $action = shift;
my $x = 11;
eval qq{
  sub {
# Some interesting code here...
$action;
  }
};
  }

 IMHO the current behaviour is intuitive.  And I certainly don't
 see action at a distance.  The person who thinks that the '$x' inside
 $str is referring to the currently visible $x (value 7) is simply
 mistaken.  Likewise the person who thinks that the inner $x will remain
 untouched by the eval().  (But maybe this latter is what Uri is
 referring to as action at a distance.)

I agree that Perl's behaviour is logical.  However it is
inconvenient.  And from the point of the person who is
trying to use make_generator, it causes internal details
to matter too much.

A workaround, of course, is to tell the person to use
global variables.  Which works except for the variables
that happen to be used internally in make_generator,
which the person doing the calling should not need to
know but does.

Cheers,
Ben
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-15 Thread Bob Rogers
   From: Kripa Sundar [EMAIL PROTECTED]
   Date: Mon, 15 Aug 2005 14:04:48 -0400

   Dear Ben,

  another bad point about eval is that it can access and modify lexicals
  and globals anywhere in the code. so that can lead to action at a
  distance and very hard to find bugs.
 [...]
I'm not sure if this is what is referred to, but it applies.

If this is dynamic code where the string to be evaled is
passed in from elsewhere, then one problem is that you
might wind up picking up lexicals in the scope of the
eval, and being unable to pick up lexicals in the scope
where you tried to create the eval.  Closures would get
this right.

Amen.

Ruby solves this problem by giving you a number of
variations on eval, one of which evals things in the
context of your caller.  Still not perfectly general, but
much more likely to be right in this instance.

And not as robust as calling a closure would be.

   Do you mean examples like below?

   --\/BEGIN-\/--
   % perl -le 'my $x = 7; my $str = q{print ++$x}; {my $x = 11; eval $str}'
   12
   %
   --/\-END--/\--

   IMHO the current behaviour is intuitive.  And I certainly don't
   see action at a distance.  The person who thinks that the '$x' inside
   $str is referring to the currently visible $x (value 7) is simply
   mistaken . . .

True, but that just means that the scope of $x in the string depends on
where you eval it; if evaluated in multiple contexts, it might have
different meanings in each of those contexts.  Contrast this to a
lexical sub, which has a single fixed meaning that can be determined by
expecting the definition context only.

   Consider the following variation on your example:

[EMAIL PROTECTED] perl -le 'my $x = 7; my $sub = sub {print ++$x}; {my 
$x = 11; $sub; }'
8
[EMAIL PROTECTED] 

So the behavior of eval is counterintuitive if you are expecting lexical
scoping.  (Which you should be, given all those my variables.)

   I'm sure this is what Ben meant by Closures would get this right.
(Sorry if I'm stealing your thunder, Ben.)

-- Bob Rogers
   http://rgrjr.dyndns.org/
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-14 Thread Mark J. Dulcey
Kripa Sundar wrote:
 I could think of three problems with eval(), and replied to him with
 the three points below.  Please let me know if I have gotten anything
 wrong below.  Also, if you can think of more eval() concerns, please
 help me learn.  TIA.

I think you've pretty well covered the ground there; I can't think of 
any more issues. Using eval() when you don't need it is like using a 
club when a flyswatter will do. It's a nice tool to have when you really 
do need a club, but best reserved for only those times.
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


[Boston.pm] Trying to learn about the problems with eval()

2005-08-14 Thread Bob Rogers
   From: Kripa Sundar [EMAIL PROTECTED]
   Date: Sun, 14 Aug 2005 18:15:08 -0400

   Dear fellow mongers,

   I saw a friend using an eval() where it was unnecessary.  Of course,
   eval() is a valuable tool, with many valid uses.  But in this specific
   instance, it was truly unnecessary, and so I advised him to eliminate
   the eval().  (The code he used was eval $string, where the value of
   $string was known at compile-time.)

   . . .

   I could think of three problems with eval(), and replied to him with
   the three points below.  Please let me know if I have gotten anything
   wrong below.  Also, if you can think of more eval() concerns, please
   help me learn.  TIA.

My favorite brief against this form of eval is that it obscures the
control flow, and this case sounds like an excellent illustration.
Rather than:

my $string = join(\n,
  'do_something($to_something);'
  '$some_other_thing = do_something_else();');
eval $string
if ($@) ...

I would much rather write:

eval {
do_something($to_something);
$some_other_thing = do_something_else();
};
if ($@) ...

In fact, I wouldn't even swear I understood how $to_something and
$some_other_thing are scoped in the first case.  (Not that I believe
I'll ever need to know.)

-- Bob Rogers
   http://rgrjr.dyndns.org/
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-14 Thread Uri Guttman
 MJD == Mark J Dulcey [EMAIL PROTECTED] writes:

  MJD Kripa Sundar wrote:
   I could think of three problems with eval(), and replied to him with
   the three points below.  Please let me know if I have gotten anything
   wrong below.  Also, if you can think of more eval() concerns, please
   help me learn.  TIA.

  MJD I think you've pretty well covered the ground there; I can't think of 
  MJD any more issues. Using eval() when you don't need it is like using a 
  MJD club when a flyswatter will do. It's a nice tool to have when you really 
  MJD do need a club, but best reserved for only those times.

i second that. using a more powerful tool than needed is a bad
programming practice. he will jump to using eval since he doesn't seem
to care about his code quality.

another bad point about eval is that it can access and modify lexicals
and globals anywhere in the code. so that can lead to action at a
distance and very hard to find bugs.

send a copy of perl best practices to him and watch his eyeballs hit the
floor when he sees how many other of damian's rules he is breaking. :)

uri

-- 
Uri Guttman  --  [EMAIL PROTECTED]   http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs    http://jobs.perl.org
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-14 Thread Tom Metro
Kripa Sundar wrote:
 I saw a friend using an eval() where it was unnecessary.
 (The code he used was eval $string, where the value of
 $string was known at compile-time.)
[...]
 * delayed error detection and impact on correctness:
 If there is a typo in the system() string that you constructed,
 such as a missing quote mark or extra open parenthesis, the problem
 will not be detected until all the preceding execution is complete.
 If the preceding code did something permanent (i.e, something that
 has life beyond the process itself) we will be left with a messy
 situation.  e.g.: if the preceding code renamed a file to a
 temporary location, with the expectation that it will be restored
 at the end of the script, then the incomplete run (caused by the
 delayed error detection) can cause problems that are hard to fix.

You seem to be blending the concepts of eval and system.

The delayed syntax checking problem can be mitigated by using the block 
variation of eval (eval {}).

Your comments about doing something that has life beyond the process 
itself and incomplete run seem a bit muddled and not consistent with 
how eval behaves. Yes, as another poster pointed out, if you don't check 
$@ after an eval, an error (compilation or otherwise) can go unnoticed, 
if that's what you mean.


 * efficiency:
 It causes the perl interpreter to be launched at run-time.

eval certainly isn't efficient, but it isn't quite as bad as you imply. 
It's not as if a new process is forked and executed. As I understand it, 
the penalty is in having to compile the eval'ed code, but that 
compilation is done by the same interpreter process running your script.

I'm not sure how much overhead the block form of eval imposes, if the 
eval'ed code doesn't vary at run time.


 * security:
 ...eval() opens us up for security problems caused by human error.

The security implications will be highly dependent on where your $string 
comes from that is being eval'ed. If it is built programmatically from 
constants within the code or using validated (untained) data, then it 
isn't much less secure than many other Perl constructs.


 Of course, eval() is a valuable tool, with many valid uses.

It (more specifically the block form) seems to get used a lot these days 
as a way to as a way to catch exceptions - a Perl equivalent for 
try/catch. (Of course there is a module on CPAN that implements 
try/catch, I assume using eval.)

  -Tom
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm


Re: [Boston.pm] Trying to learn about the problems with eval()

2005-08-14 Thread Uri Guttman
 TM == Tom Metro [EMAIL PROTECTED] writes:

  TM Your comments about doing something that has life beyond the process 
  TM itself and incomplete run seem a bit muddled and not consistent with 
  TM how eval behaves. Yes, as another poster pointed out, if you don't check 
  TM $@ after an eval, an error (compilation or otherwise) can go unnoticed, 
  TM if that's what you mean.

it's easy enough to benchmark. just write a simple line of code like $x
= 3 and also eval the same code string.

the issue isn't the actual speed of eval but that we know it takes some
real time and it isn't needed. so that is just cpu waste for lack of
understanding of string eval.

   * efficiency:
   It causes the perl interpreter to be launched at run-time.

  TM eval certainly isn't efficient, but it isn't quite as bad as you
  TM imply.  It's not as if a new process is forked and executed. As I
  TM understand it, the penalty is in having to compile the eval'ed
  TM code, but that compilation is done by the same interpreter process
  TM running your script.

it invokes a full interpreter, then it compiles the code and then it
executes it. compare that to just executing the code which is what you
get if you avoid string eval. this is also just the efficiency reason as
opposed to the safety, bug causing, confusing, overkill and global hell
reasons.

my rule for symrefs and string eval apply here: only those who know when
not to use string eval are allowed to use it.

  TM I'm not sure how much overhead the block form of eval imposes, if
  TM the eval'ed code doesn't vary at run time.

it is compiled with all the other top level code at compile time. block
eval has one purpose which is to catch dies. it was a major mistake
(like with select) to name different things to the same name. so block
eval isn't any slower than any other normal code.

  TM It (more specifically the block form) seems to get used a lot
  TM these days as a way to as a way to catch exceptions - a Perl
  TM equivalent for try/catch. (Of course there is a module on CPAN
  TM that implements try/catch, I assume using eval.)

block eval is the only way to do exceptions in perl and it is just for
its try/catch behavior with die. it has no relationship to string eval
so even say the block form is slightly confusing as it implies a deeper
connection. perl6 has it named properly as a CATCH block you declare
inside a block. it will catch any exceptions inside that block and it
has ways to filter out what exceptions it handles and which are passed
up the call chain.

so please tell this cow-orker that string eval is only to be used when
it is the only or absolutely best solution. anything else means the
problem can be and should be solved with normal compile time code.

uri

-- 
Uri Guttman  --  [EMAIL PROTECTED]   http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs    http://jobs.perl.org
 
___
Boston-pm mailing list
Boston-pm@mail.pm.org
http://mail.pm.org/mailman/listinfo/boston-pm