Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

From PHP development I know that eval is evil and I've recently read What constitutes “Proper use” of the javascript Eval feature? and Don't be eval. The only proper use of eval I've read is Ajax.

I'm currently developing a visualization tool that lets users see how polynomials can interpolate functions:

enter image description here

I use eval for evaluation of arbitrary functions. Is this a legitimate use of eval? How could I get rid of eval?

I want the user to be able to execute any function of the following forms:

  1. a x^i with a,i in R
  2. sin, cos, tan
  3. b^x with b in R
  4. any combination that you can get by
    • adding (e.g. x^2 + x^3 + sin(x)),
    • multiplying (e.g. sin(x)*x^2) or
    • inserting (e.g. sin(x^2))
share|improve this question
1  
You might use a math library on it, for example: mathjs.org which takes care of parsing. –  Luc Franken Jul 1 '13 at 8:54
7  
"Eval is evil" is just the same degree of ignorance as the classic stupid rant "goto is evil". Eval is a legitimate and powerful tool for runtime metaprogramming. –  SK-logic Jul 1 '13 at 9:09
1  
@SK-logic but you need to tread lightly, and there's normally a better way. –  Jan Dvorak Jul 1 '13 at 9:11
    
@JanDvorak, metaprogramming is nearly always a better way than anything else. With languages like JavaScript there is no distinction between compile-time and runtime metaprogramming, therefore eval is a legitimate way of doing nearly everything (in absence of proper macros). –  SK-logic Jul 1 '13 at 9:13
    
@SK-logic Metaprogramming is good if it's what you want. And when you want metaprogramming, there's more tools for metaprogramming than eval. eval is without a doubt the most powerful, but it's also more brittle and dangerous than more specialized tools. For example, there is no reason to use eval for getting an attribute dynamically, as in eval('obj.'+attrname) - that's what obj[attrname] is for. –  delnan Jul 1 '13 at 9:23
show 3 more comments

3 Answers

up vote 7 down vote accepted

I see nothing not "legitimate", eval isn't evil per se and it has been precisely designed to evaluate arbitrary code. It lets you here make a fast, complete expression evaluator without resorting to complex libraries and it gives your user the power of JavaScript.

But right now you're evaluating the input for each x. This is very slow.

I would do this so that it can be used more efficiently :

var f = Function('x','return '+input);

When input is Math.sin(x), this builds a function you can simply call as

var x = 3;
var y = f(x);

Proof : jsperf


If what you want is to let the user enter function with a more classical mathematical language (like x^y), then you'd better start importing a mathematical expression parser.

An example of such a library : Silent Mat's evaluator

share|improve this answer
    
What about the ^ for exponentiation, as delnan pointed out? –  Jan Dvorak Jul 1 '13 at 8:59
1  
@JanDvorak There are functions in JavaScript just for that, like Math.pow. The point here is not to have to interpret the symbolic expression. –  dystroy Jul 1 '13 at 9:00
1  
Well, eval definitely is evil. evil, n.: something you should avoid most of the time, but not something you should avoid all the time (C++ FAQ 6.15). This time seems not to be most of it. –  Jan Hudec Jul 1 '13 at 11:12
    
@JanHudec It's JavaScript, not C++. Most "eval is evil" stances are just FUD. –  dystroy Jul 1 '13 at 11:13
2  
C++ does not have many evil constructs. It was designed by an expert to ease the work of other experts. It has many constructs that have been widely misused by inexpert programmers. –  kevin cline Jul 1 '13 at 13:07
show 3 more comments

A lot of people who know eval is dangerous on the server side also reflexively shun it on the client side. There is a huge difference. It is not a security hole to be able to execute your own arbitrary code on your own computer. The only time to be concerned about eval security on the client side is if you're using it to execute code from an untrusted third party, for example from email or a twitter feed.

However, there are other factors to consider. The eval solution is going to be much simpler for basic functionality, but much more difficult to add things like useful error messages. You may end up implementing your own parser anyway to add those sorts of features.

There are also performance considerations, but I think the difference is likely to be negligible. eval will probably have higher startup times, but faster execution times.

Personally, I would use eval for a tool for my own use or within my company, for its simplicity of development. For wider distribution, I would want the polish a custom parser can provide.

share|improve this answer
add comment

You don't want to evaluate Javascript functions. You want to evaluate some subset of the computable functions from the reals to the reals. So eval doesn't do what you want, although in principle you may be able to abuse it for that. Apart from this philosophical objection, if you want to use ^ for exponentiation, you can't use eval because it uses Javascript syntax where ^ is binary xor.

If you just want to be done quickly and leave this project, you can use eval (especially since this apparently runs on the client site, so the potential for abuse is limited). But the right thing(tm) to do would be using an expression parser specifically for the kind of syntax you want to allow, coupled with an evaluation routine for the parsing output.

It's not that hard to write such a thing yourself, and quite fun. I'd use either the shunting-yard algorithm or a top down operator precedence parser. Alternatively, use an existing library as recommended in the comments.

share|improve this answer
    
I don't want to use ^ for exponentiation. It's up to the user to use the correct syntax as I've noted in the application. I just used this here to make it easier to read. –  moose Jul 1 '13 at 9:05
    
Eval is supposed to be efficient, whereas your ad hoc interpreter is never going to reach the underlying javascript performance. Therefore, the best approach is to compile your simple DSL into JavaScript and then eval the resulting code. –  SK-logic Jul 1 '13 at 9:10
    
@SK-logic If the evaluation of the function is the bottleneck, yes. Otherwise it's probably not worth the extra twenty lines. While we're talking about performance, note the point of another answer that repeated eval would needlessly parse the JS code again and again. –  delnan Jul 1 '13 at 9:13
    
@delnan, and for plotting it is a bottleneck indeed (since it's an inner loop body). And even if performance is not an issue, there is not much point in reinventing an execution engine if one is already available. –  SK-logic Jul 1 '13 at 9:15
    
@SK-logic I've never created a plotter, so I refrain from guessing. And in my experience, just evaluating simple math is simpler than robustly mapping it to another language. For such simple operations, evaluation is trivial. –  delnan Jul 1 '13 at 9:18
show 11 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.