我读到fsi.exe (f# Interactive)在严格意义上不是一个真正的"解释器",因为它动态编译 f#代码并显示其输出。
我的印象是"解释器"这个词适用于"动态"语言(即JavaScript),因此不适用于f#,因为它是一种编译语言。
这是一个公平的评估吗?或者编译语言可以被"解释"?或者这只是一个语义问题?感谢任何帮助。
编译和解释之间的区别是模糊的。许多被认为是"解释型"的语言实际上经常被编译成本地代码(例如,JavaScript v8)。动态语言中最具动态特性的eval
的一些实现只是对编译的包装(例如,在SBCL中)。
当然,REPL与编译或解释无关,REPL可以构建在任何执行模型之上。fsi
只是一个REPL,它使用与fsc
相同的f#编译器核心
我的印象是"口译员"这个词;适用于"动态";因为f#是一种编译语言,所以它并不适用于f#。
这是一个公平的评估吗?。"口译员"这个词;指程序执行的方式。如果一个源程序是通过一个叫做"解释器"的独立程序来执行的;它通过解释源程序中每条指令的含义来执行它,然后它被解释。
术语"动态编程语言";似乎没有正式的定义,只是非正式地使用,通常指动态类型语言(即缺乏静态类型系统,因此将所有类型检查推迟到运行时)或能够在运行时实现功能的编程语言,例如宏,反射,reps等。这与程序是被解释还是被编译无关。例如,Common Lisp被视为动态语言,OCaml被视为静态语言(尽管它同时具有宏和REPL),但是Common Lisp和OCaml都可以使用解释器和编译器。
或者编译语言可以"解释"?
再一次,术语"编译语言"是不明确的。任何语言都可以被解释或编译。从形式上讲,任何可执行语言都可以被解释,任何解释器都可以通过在源程序上部分专门化而变成编译器。
请注意,一些编程语言实现同时使用编译和解释,以便获得两者的优点。例如,OCaml可以使用用OCaml编写的编译器将程序编译成字节码,然后由用c编写的解释器解释字节码。这有几个优点:
- 比普通的术语级解释器快得多。
- 比针对x86等机器码的本机代码编译器简单得多。
- 编译阶段可以执行优化(例如大步语义),解释器从中受益,而不必看到。
- 简单性使得用C编写解释器变得容易,从而进一步提高了性能。
或者这只是一个语义问题?
术语。
当你说JavaScript是"动态的"时,你通常指的是"动态类型的",这与它通常被实现为解释语言而不是编译的事实无关。"动态类型"的反义词是"静态类型"。注意,这与"弱类型"one_answers"强类型"描述的属性是不同的。这两个属性都与解释器和编译器无关,除了脚本语言(几乎总是解释的)倾向于动态类型。
编译器显然是(好吧,实际上,这个问题是关于一个编译器作为一个解释器,但让我们去与这个争论的缘故)不是一个解释器,所以如果你编译一些源代码到一个目标文件并执行它,你会认为它显然没有解释。但事实证明,这条线并不是很明确。如果您认为模拟器是解释器,那么您可以解释任何可执行文件,无论它最初是什么语言。还有二进制翻译和JIT编译器,它们的字节码使本已令人困惑的问题变得更加复杂。但请注意,这里的混乱完全是语义上的,解决方案可能只是更新了一组定义。
相反,你可以通过记录解释器在解释程序时所做的指令并将其作为编译后的程序回放来"编译"任何解释性语言。这不是真正的编译,它不会比解释器更有效,但关键是被解释并不是语言的内在品质。
因此,传统上编译的语言可以,并且有时被实现为解释语言。甚至还有C语言的解释器。我相信这已经回答了你的问题。我认为关于f#的观点是,尽管它是交互式的,但根据最严格的定义,它并不是一个真正的解释器。这是因为它先编译代码位,然后再运行它们。这并不意味着由于f#语言的某些属性,就不能为f#编写严格的解释器。撇开学术上的争论不谈,与FSC编译成可执行文件的代码相比,FSI执行的代码运行时没有明显的性能下降。在这方面,f#优于OCaml - ,参见Harrop关于OCaml顶层的评论。
查看解释器维基百科文章,我们发现:
一个解释器可能是一个程序…将源代码转换成某种有效的中间表示形式(代码),并立即执行。
…