eval()的威力是什么?

3

最近我在几个地方(一些D和JavaScript代码)看到了eval()函数。这让我意识到我并不理解有或没有eval()的语言之间的区别。

事实上,我一直能够在没有使用它的情况下生存下来(尽管有时很诱人 :))。

你知道实现eval()的语言和不实现它的语言(即使是在编译时)之间是否存在任何基本差异吗?如果没有基本差异,是否存在表达差异?

你知道有没有任何论文或参考资料,解释eval()提供的增强计算能力/表达能力是什么?也就是说,我们可以用eval()实现什么,而不能在没有它(或成本更高)的情况下实现?


在我看来,没有实现eval的编程语言是默认其用户非常愚蠢的。 - Markus Unterwaditzer
@MarkusUnterwaditzer:我从未听说过有人声称C或汇编语言假定其用户是愚蠢的。这是新的说法。 - Dietrich Epp
1个回答

4
没有eval和有eval的语言在能力上没有区别。在不支持eval的语言中,你总是可以自己实现eval,尽管在某些语言(如Lisp)中更容易,在其他语言(如C)中则更困难。这就是为什么我们知道它不会为语言增加任何新的功能。
通常认为eval“功能强大但在生产代码中却危险且不必要”。如果您的源代码经过审核,并且使用了eval,则您将不得不习惯于人们告诉您不要使用eval。通常,如果您使用eval,那么完成相同任务的更直接和更安全的方法是存在的。
安全漏洞
eval函数通常会导致安全漏洞,例如在Web应用程序中。例如,在Python中:
i = input('Enter a number> ')

Python 3.x之前版本中的input函数会对用户输入进行求值,导致安全问题:

请输入一个数字> __import__('os').system('rm -rf $HOME') # 不要尝试此操作

在完全沙盒运行时(如JavaScript、Lua、CLI等)可以避免这种情况。然而,在非沙盒代码中,使用eval是非常困难的。

REPL

eval的一个重要用途是REPL,这是软件开发中非常有用的工具。在Google Chrome 中,您可以通过按Ctrl+Shift+I打开REPL - 只需在弹出的框中开始键入JavaScript即可。Firefox和Safari也都有 REPL。

为什么不包括eval

eval函数通常非常复杂。将其包含在标准库中意味着库或运行时必须包含完整的语言编译器或解释器,这是一大堆代码。这就是为什么通常在通常被解释或 JIT 的语言中看到eval - Lisp,Python和JavaScript运行时通常已经包括完整的编译器,因此eval没有额外的负担。

C语言中的eval实现是真正的巨兽,因此它们是可选的并且被推入库中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接