spurperl has asked for the wisdom of the Perl Monks concerning the following question:
I need to enlighten some newbies re the usage of string eval. I want to show relatively small and simple examples in which string eval saves the day, beating the other approaches. That is, the examples have to be real-life, something that shows "live" how the eval is useful, not toy examples.
It is preferable to see code generation examples (I suspect that most real useful uses of string eval are for on-the-fly code generation).
Your help will be most appreciated. Thanks in advance
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Small examples of string eval
by gellyfish (Monsignor) on May 13, 2006 at 07:53 UTC | |
This is the only real example I could find in my own code, essentially it is a method on a base collection class to cause the collection to appear to be sorted on an arbitrary attribute (or attributes) of the objects in the collection. It uses eval to dynamically create a sort sub from a list of comparison specifications passed as an argument. Okay it doesn't fit the the 'small' criteria but I think it is illustrative of the kind of use string eval is good for:
/J\ | [reply] [d/l] |
by brian_d_foy (Abbot) on May 14, 2006 at 17:06 UTC | |
You don't need a eval to do this, and it's easier to do without it. You basically want a higher order function that composes other functions, and all of the functions are going to get the same arguments. Starting from the finished product, you might have a sort subroutine like this, where the return value is the first thing that returns true (which should be -1 or 1).
That's the same as writing it as a collection of subroutines that get arguments instead of using globals though:
But I can rewrite that sortsub to take a list of subroutine references as its arguments. Now my sortsub goes through each subroutine and returns when it finds one that returns a true value. If it finds 0 (meaning that sub thought the elements were equal), it goes onto the next subroutine.
I can't use this in sort yet because I can't pass it arguments. I can, however, modify it to return a subroutine reference I can use:
Now, I basically make the reference then use it in my sort block.
And here's a full demo, using it with numbers, then strings, then a user-defined sort subroutine. I don't need an eval for any of it.
| [reply] [d/l] [select] |
by spurperl (Priest) on May 13, 2006 at 08:37 UTC | |
Unlike what many think, although the string eval is dangerous, it is necessary to efficiently and generically implement certain things that are impossible without it. The terrific "Higher Order Perl" has a lot of examples for smart usage of eval, and I'll look there as well. | [reply] |
Re: Small examples of string eval
by BrowserUk (Patriarch) on May 13, 2006 at 10:20 UTC | |
I have several scripts that take numeric arguments from the command line where is is extremely useful to be able to enter expressions instead of simple values.
This way I can specify
Which beats the crap out of trying to remember
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
by brian_d_foy (Abbot) on May 14, 2006 at 17:16 UTC | |
You don't need eval for that, even if it makes it easier than parsing the argument and figuring out the value. The downside is that anyone can run arbitrary code using your script. With a tiny bit of programming you can do the math yourself and save yourself the security problem. :)
| [reply] [d/l] |
by BrowserUk (Patriarch) on May 14, 2006 at 19:05 UTC | |
anyone can run arbitrary code using your script ... Apart from the fact that only I run the scripts in question, those same bad people you are parnoid about could also type perl -e"the same arbitrary code" With a tiny bit of programming ... Show me the code. Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
by brian_d_foy (Abbot) on May 14, 2006 at 20:04 UTC | |
by BrowserUk (Patriarch) on May 14, 2006 at 21:40 UTC | |
by BrowserUk (Patriarch) on Jun 10, 2006 at 09:44 UTC | |
Re: Small examples of string eval
by graff (Chancellor) on May 13, 2006 at 07:00 UTC | |
The one thing where eval is basically unavoidable is the use of a string variable within the "tr///" operator. It's simple, basic, and has a bunch of obvious uses in "real-life". (update: forgot to include an example...)
| [reply] [d/l] |
by ikegami (Patriarch) on May 13, 2006 at 07:29 UTC | |
In my opinion, eval EXPR (as opposed to eval BLOCK) should be used only as a last resort. Your code is a prime example. It breaks as soon as someone places -, } or \ in %charmap. The following does not, and avoids eval EXPR entirely:
(No, the /e is not the same as eval EXPR. There's no dynamic code generation. /ee, on the other hand, would be the same as eval EXPR.) | [reply] [d/l] [select] |
by spurperl (Priest) on May 13, 2006 at 07:28 UTC | |
Thanks for the example, but it's not what I'm looking for. Your example is very idiomatic to Perl, I'd say it's a patch on a deficiency, because I have no trouble imagining tr/// implemented in such a way that allows the trick without eval. What I'm looking for is more in the code-generation league. Generate some code with eval, on the fly, and call it when necessary. | [reply] |
by ikegami (Patriarch) on May 13, 2006 at 07:44 UTC | |
Major code generation is usually used when a language is inept (or not particularly adept) at doing something. Off the top of my head, I can think of three reasons why a language would be inept at doing something | [reply] |
Re: Small examples of string eval
by eyepopslikeamosquito (Archbishop) on May 13, 2006 at 12:37 UTC | |
Most Perl experts discourage the use of string eval. For example: Update: In this quiz of the week MJD states: A good rule of thumb is that unless what you're trying to do is most clearly described as "compile and run arbitrary Perl code", it's probably a mistake to use 'eval' to do it. | [reply] |
by BrowserUk (Patriarch) on May 13, 2006 at 18:12 UTC | |
But each of them knows when to eshew complicated eval-avoidance-schemes, in favour of simplicity. merlyn See name_to_page() in CGI::Prototype::Hidden, new() in CGI::Prototype::Mecha, type() in File::Finder, the grammer for Inline::Spew. TheDamian See import() in Attribute::Handlers, import() in Attribute::Types, install_dispatch() in Class::MultiMethods, initialise() & new() in Class::Std... I stopped here with D-Z to go. Dominus memoize() in Memoize, in Memoize::AnyDBM_File, fill_in() inText::Template, TIEARRAY() in Tie::File. And before anyone leaps to these authors defense, there is no need. String eval is a tool. Avoiding it where practical is common sense; eshewing at all costs is illogical. I'm betting that Perl6 will retain string eval in some form. Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
by spurperl (Priest) on May 14, 2006 at 03:59 UTC | |
I really hope Perl 6 won't drop the string eval, having it IMHO is essential to any dynamic language. | [reply] |
by stvn (Monsignor) on May 13, 2006 at 15:12 UTC | |
He (TheDamian) further advises you to use anonymous subroutines and the CPAN Sub::Installer module when you have a need to create new subroutines that are built around some expression that the user supplies. While Sub::Installer is certainly a good idea (insulating the user from the evils of symbol table manipulation, which is at least as dangerous as string eval in the 'wrong' hands). It's code can hardly be considered to contain "Best Practices" IMO. It clearly abuses UNIVERSAL in a way which affects not only the code which uses it, but all other running Perl code. This is the offending code: This would mean that every Perl object will respond true to the query $object->isa('Sub::Installer'). Again, IMO, that is not a Best Practice, but instead a really really bad idea. Sorry, I am a little passionate about code which tramples over the Perl 5 object model like this. But fear not! CPAN will save the day. As an alternative, I offer Sub::Install an excellent module which does not assert it's will upon your entire runtime.
-stvn
| [reply] [d/l] [select] |
Re: Small examples of string eval
by UnderMine (Friar) on May 13, 2006 at 09:13 UTC | |
UnderMine | [reply] [d/l] |
Re: Small examples of string eval
by tilly (Archbishop) on May 15, 2006 at 06:44 UTC | |
| [reply] |
Re: Small examples of string eval
by ruzam (Curate) on May 14, 2006 at 03:16 UTC | |
1) retrieving stored hashes I regularily used Data::Dumper to turn hashes into strings so they can be stored in a database for later retrieval. The string accurately represents the original hash with out my having to do a thing and it's safe to store anyway I have to, flat files, dbm, mysql. When the data is later retrieved, eval is the easiest way to get it back into a useful hash. Something like this:
1) wrapping DBI calls to capture errors. Far as I know this is the recommended (only?) way to do this. More generically I guess you could say eval is the tool of choice when ever you have to call code beyond your control that may kill your script. | [reply] [d/l] [select] |
by eyepopslikeamosquito (Archbishop) on May 14, 2006 at 03:43 UTC | |
That is an example of block eval, not string eval; the OP was asking about string eval. There is wide agreement that block eval is a good thing in Perl 5 (for exception handling). Overloading eval with two different meanings in Perl 5 was unfortunate and is fixed in Perl 6, where block eval is spelled try. | [reply] [d/l] [select] |
Re: Small examples of string eval
by aufflick (Deacon) on May 15, 2006 at 07:08 UTC | |
eval EXPR is what I use in php or Sybase stored procedures, to make up for the lack of expressiveness in the language. While eval EPXR has definite uses (such as the quoted example of dynamically loading packages), probably 90% of the times that eval EXPR is used in Perl code, faster and more safe code could be written to do the same thing using techniques such as those shown in other responses (such as closures/currying etc.). In fact, if these developers are serious C or Java developers and talk about things like compiler optimisations then they are going to recognise most eval EXPR based Perl code as a weak solution to hard problems. It would be sad for that to be their first Perl experience as Perl offers such better solutions to those problems than does, say, C or Java. | [reply] |
Re: Small examples of string eval
by eyepopslikeamosquito (Archbishop) on May 15, 2006 at 09:30 UTC | |
A historic example of string eval that springs to mind is Larry's famous rename script. See also Unix rename faq (a version of Larry's script is given at the end) and the Perl Cookbook, recipe 9.9. And though these may set a poor example for newbies, please notice that Acme::Bleach: Acme::Buffy: and Acme::EyeDrops: all rely on good ol' string eval to perform their magic. :-) | [reply] [d/l] [select] |
Re: Small examples of string eval
by jwkrahn (Abbot) on May 13, 2006 at 23:40 UTC | |
[reply] | |
by ikegami (Patriarch) on May 14, 2006 at 04:24 UTC | |
Check out NestedLoops in Algorithm::Loops. In this case,
I suspect that
| [reply] [d/l] [select] |
Re: Small examples of string eval
by DrHyde (Prior) on May 15, 2006 at 09:22 UTC | |
It is important to note that "SUPER" refers to the super-class(es) of the current packageso instead of just doing this: I have to do this: Block eval won't cut it here, and while I'm sure plenty of people are going to bleat that this travesty just demonstrates that my design was wrong in the first place (and I'd agree) in the real world one doesn't always know what all the requirements are when one starts writing code. I decided it was better to write a couple of lines of ugly code - and comment what I was doing and why - than to spend literally days re-jigging everything else so that I could then write that tiny snippet of functionality more cleanly. | [reply] [d/l] [select] |
Re: Small examples of string eval
by DrHyde (Prior) on Jun 22, 2006 at 11:12 UTC | |
| [reply] |