tags:

views:

414

answers:

7

Another question inspired this one:

Mostly everybody agrees that eval is bad, and in most cases there is more elegant / safer replacement.

So I wanted to ask: if eval is misused that often, is it really needed as a language feature? Is it doing more evil than good?

Personally, the only place I find it useful is to interpolate strings provided in config file.

Edit: The intention of this question is to get as many real-life cases as possible when eval is the only or the best solution. So please, don't go into "should a language limit a programmer's creativity" direction. Thanks!

Edit2: And when I say eval, of course I refer to evaling string, not passing ruby block to instance_eval or class_eval.

+1  A: 

The reason eval is there is because when you need it, when you really need it, there are no substitutes. There's only so much you can do with creative method dispatching, after all, and at some point you need to execute arbitrary code.

Just because a language has a feature that might be dangerous doesn't mean it's inherently a bad thing. When a language presumes to know more than its user, that's when there's trouble.

I'd argue that when you find a programming language devoid of danger, you've found one that's not very useful.

When is eval justified? In pragmatic terms, when you say it is. If it's your program and you're the programmer, you set the parameters.

tadman
The only thing I might add is "it's justified when you say it is AND you are aware of the ramifications".
Bryan Oakley
My intention was to get as many justified eval usages as possible, not to argue whether Ruby author(s) did the right thing. But if you want to go there, I'd say that often I am not the only one who set the parameters, as you say, as often I am not the only programmer on the project. And eval is one of the most dangerous language features, fallen in wrong hands.
Mladen Jablanović
-1. Generalizations and putting the ball back in MLaden's court don't help anyone.
z5h
@z5h I'm not sure how what I said is an invalid answer. If you're working on a project, there will be many conventions and parameters you will have to conform to, one of which might be to not use eval, but that really is someone's judgement call. I did my best to answer the question of why eval is even part of Ruby, or when you can use it. As the post here is rather philosophical in nature, it seems peculiar you're offended by a philosophical answer.
tadman
Not at all offended. And I'm not implying your post was invalid. I just felt the generalizations were not helpful in this case.
z5h
+1  A: 

IMO mostly for Domain Specific Languages. There is an article of Jay Fields about it on InfoQ

Diego Dias
A: 

eval is a tool, it is neither inherently good nor evil. It is justified whenever you are certain it is the right tool for what you are trying to accomplish.

Bryan Oakley
I mostly agree. The problem is when those who abuse the eval-hammer start breaking things just because they don't know the language; like, they rewrite the RTL or something.
The Wicked Flea
@The Wicked Flea: that's why I included "whenever you are certain". If you think it's the right tool, it's not. It's only when you know it's the right tool and know the ramifications of that decision that it is indeed the right tool.
Bryan Oakley
Well, being certain doesn't automatically make your decisions justified. Also, I'd argue that some tools are being used for benign purpose more often than others (a plow and a bomb come to mind). Heh, a political comment for a political answer. :(
Mladen Jablanović
Right on. Just because tools are dangerous doesn't mean they're not useful. A power saw, by way of analogy, is extremely dangerous, but at the same time, an invaluable tool.
tadman
A: 

A tool like eval is about evaluating code at runtime vs. "compile" time. Do you know what the code is when you launch Ruby? Then you probably don't need eval. Is your code generating code during runtime? then you probably need to eval it.

For example, the methods/functions needed in a recursive decent parser depend on the language being parsed. If your application builds such a parser on-the-fly, then it might make sense to use eval. You could write a generalized parser, but it might not be as elegant a solution.

Here is a question I posted about eval (in Scheme), where it's use is mostly unavoidable. http://stackoverflow.com/questions/1895399/programatically-filling-in-a-letrec-in-scheme-macros-or-eval

z5h
You can generate functions at runtime without using eval.
Chuck
Write code that generates a set of mutually recursive functions without eval. Then with eval. My contention is that the second exercise will usually be simpler.
z5h
In Ruby, the way to generate methods with and without `eval` is almost the same, so I'm not sure why this would be different?
dvyjones
I'm talking about code that completely *generates* the string to be eval-ed. It doesn't just fill in a couple values in a template then evals. Especially when that generated code contains a set of mutually recursive functions (they all call into each other). Also, I never said it's the only way to do things, just possibly simpler.
z5h
I would actually like to test that hypothesis, but no cases where I'd want to do what you're describing come to mind. Can you think of any where the whole effort wouldn't just be needless gold-plating?
Chuck
I posted a link to an example I came up with in Scheme and discussed on SO. I feel the situation would be similar. Even in my example, it's not totally needed, but then I'd incur the overhead of doing checks in a function every time, when instead I can do them ahead of time, write out the functions and eval once.
z5h
+4  A: 

The only case I know of (other than "I have this string and I want to execute it") is dynamically dealing with local and global variables. Ruby has methods to get the names of local and global variables, but it lacks methods to get or set their values based on these names. The only way to do AFAIK is with eval.

Any other use is almost certainly wrong. I'm no guru and can't state categorically that there are no others, but every other use case I've ever seen where somebody said "You need eval for this," I've found a solution that didn't.

Note that I'm talking about string eval here, by the way. Ruby also has instance_eval, which can take either a string or a block to execute in the context of the receiver. The block form of this method is fast, safe and very useful.

Chuck
+1. This has more useful information than the current leading answer.
z5h
I know that this goes beyond the scope of the primary question, but I'm curious in which real-usage cases you need to dynamically assign local/global variables, i.e. when using instance attributes and appropriate methods instance_variable_set and instance_variable_get doesn't work?
Mladen Jablanović
Well, you don't always want to store things past the method invocation, and sometimes you want to use local variables to determine what ivars get set to. One place where this can be useful is to eliminate boilerplate. Often an initializer will take arguments and assign them to identically named instance variables. With `eval`, you could abbreviate this to something like `set_ivars(binding)`.
Chuck
this idiom is useful, and only possible with eval: `eval('self', block.binding)`
banister
+1  A: 

When is it justified? I'd say when there's no reasonable alternative. I was able to think of one use where I can't think of an alternative: irb, which, if you dig deep enough (to workspace.rb, around line 80 in my copy if you're interested) uses eval to execute your input:

def evaluate(context, statements, file = __FILE__, line = __LINE__)
  eval(statements, @binding, file, line)
end

That seems pretty reasonable to me - a situation where you specifically don't know what code you're going to have to execute until the very moment that you're asked to do so. Something dynamic and interactive seems to fit the bill.

Mike Woodhouse
A: 

There is one very important use-case for eval() which cannot (AFAIK) be achieved using anything else, and that is to find the corresponding object reference for a binding.

Say you have been passed a block but (for some reason) you need access to object context of the binding, you would do the following:

obj = eval('self', block.binding)

It is also useful to define the following:

class Proc
    def __context__
        eval('self', self.binding)
    end
end
banister