昨天我和我的一个朋友开始讨论这个问题。他习惯于使用具有eval函数的解释语言(AS3,PHP)进行编码,并习惯使用编译语言(如C ++)。 然后,我试图向他解释,在编译语言中使用eval功能是不可能的,因为本机代码对其源代码(变量,语法,反射(在C / C ++的情况下)等)一无所知,并且这样,你无法使任何函数在没有编译的情况下实时执行源代码(并且为了编译它,你需要其余的源代码,所以这是不可能的。)
你怎么看?这个论点足够坚固吗?您是否会提出任何其他论据来论证为什么编译语言不能具有eval功能? (请不要发表任何反对eval想法的东西)。答案 0 :(得分:18)
编译语言可以有eval
,但二进制文件也需要包含或有权访问编译器。
如果eval
ed代码要与编译的代码交互,则二进制文件中的某些注释(例如变量名,类名,函数名,类型)是必需的。 Java .class
文件是一个很好的例子,其中仍然可以从编译的代码中收集大量信息。
答案 1 :(得分:10)
编译语言当然可以有一个eval函数(如LISP),但这意味着运行时必须包含编译器。
事实上,JavaScript可能是最好的例子。所有major implementations(V8,Charkra,SpiderMonkey)现在都编译为本机代码,但它具有eval
函数。这是有效的,因为编译器是运行时系统的一部分。
答案 2 :(得分:4)
没有真正的答案 - 语言可以编译为本机代码,并且仍然包含eval
函数。这样做并不是很受欢迎,因为它要求在每个程序的运行时基本上包含一个完整的编译器(至少每个程序使用eval
)。通常有一点妥协:不包括完整的编译器,只包含相当有限的编译器版本(例如,缺少大多数优化)或包含解释器。
答案 3 :(得分:3)
编译语言不能具有eval
功能的概念简直就是假的。由于复杂性,大多数编译语言选择不实现它,但它是可以实现的。例如
答案 4 :(得分:1)
编译语言肯定可以有eval。
例如Clojure(以及许多其他Lisps)总是被编译并支持eval,符合Lisp的“代码是数据”的理念:
(def code '(reduce + [1 2 3 4 5])) ;; create data structure containing code
(eval code) ;; compile and execute the code with eval
=> 15
这项技术真正需要的是编译器包含在语言运行库中,以便可以即时编译和执行新代码。
答案 5 :(得分:0)
我认为可以合理地说,在编译期间经过大量优化的任何代码都无法处理eval语句。为了优化工作,编译器需要识别源中可以优化的模式。如果您需要在代码中间评估命令,那么事情需要保持一定的灵活性,并且会有相关的性能损失。
答案 6 :(得分:0)
编译语言当然可以具有eval
功能,即使对于C / C ++也是如此。您只需要运行时运行编译器的某种方式,某种类型的运行时加载,如dlopen
,以加载要通过eval
运行的代码,以及某种方式使eval代码具有与运行时通信。