最近我偶然发现了几个地方的eval()
函数(一些D和JavaScript代码)。这段经历让我意识到我不理解有或没有eval()
的语言之间的区别。
事实上,我已经能够在不使用它的情况下生存(虽然有时很诱人:))。
您是否了解实现eval()
的语言与未实现该语言的语言(即使是在编译时)之间的任何根本区别?如果没有根本区别,是否有表现力差异?
您是否知道任何论文或参考文献解释eval()
提供的额外计算能力/表现力?这就是,我们可以用eval()
实现什么,没有它我们无法实现(或以更高的成本)?
答案 0 :(得分:4)
eval
语言与没有语言的语言之间的能力没有差异。你总是可以用一种没有它的语言自己实现eval
,虽然它在某些语言(Lisp)中更容易,在其他语言中更难(C)。这就是为什么我们知道它不会为语言添加任何新功能。
Eval通常被认为是“强大但危险且在生产代码中不必要”。如果您对源代码进行了审核,并且使用了eval
,那么您必须习惯告诉您不要使用eval
的人。通常,如果您使用eval
,则可以使用更简单,更安全的方式完成相同的任务。
eval
功能通常会导致安全漏洞,例如在Web应用程序中。例如,在Python中:
i = input('Enter a number> ')
3.x之前的Python中的input
函数评估用户输入,导致安全问题:
Enter a number> __import__('os').system('rm -rf $HOME') # DO NOT TRY THIS
在完全沙盒运行时(例如JavaScript,Lua,CLI等)中可以避免这种情况。但是,在没有沙箱的代码中,安全使用eval
非常困难。
eval
的一个光荣用途是REPL,它是软件开发的有用工具。在谷歌浏览器中,您可以通过按 Ctrl + Shift + I 立即启动REPL - 只需在出现的框中输入JavaScript即可。 Firefox和Safari都有REPL。
eval
? eval
功能通常非常复杂。将它包含在标准库中意味着库或运行时必须包含一个完整的语言编译器或解释器,这是一大堆代码。这就是为什么你经常在通常被解释或JITed的语言中看到eval
- Lisp,Python和JavaScript运行时通常已经包含一个完整的编译器,所以eval
不是额外的包袱。
C的eval
实现是真正的野兽,因此它们是可选的并且被推入库中。