我读过 fsi.exe(F# Interactive)在严格意义上并不是真正的“解释器”,因为它动态编译F# 代码并显示其输出。
我的印象是“解释器”这个词适用于“动态”语言(即 JavaScript),因此不适用于 F#,因为它是一种编译语言。
这是一个公平的评价吗?还是可以“解释”编译语言?或者这只是一个语义问题?
感谢任何帮助。
我读过 fsi.exe(F# Interactive)在严格意义上并不是真正的“解释器”,因为它动态编译F# 代码并显示其输出。
我的印象是“解释器”这个词适用于“动态”语言(即 JavaScript),因此不适用于 F#,因为它是一种编译语言。
这是一个公平的评价吗?还是可以“解释”编译语言?或者这只是一个语义问题?
感谢任何帮助。
编译和解释之间的区别是模糊的。许多被视为“解释”的语言实际上经常被编译为本机代码(例如,带有 v8 的 JavaScript)。动态语言中最具动态特性的一些实现,eval
只是对编译的包装(例如,在 SBCL 中)。
当然,REPL 与编译或解释无关,REPL 可以构建在任何执行模型之上。fsi
只是一个 REPL,它使用与fsc
.
我的印象是“解释器”这个词适用于“动态”语言(即 JavaScript),因此不适用于 F#,因为它是一种编译语言。
这是一个公平的评价吗?
不,“解释器”一词是指程序的执行方式。如果源程序是通过一个称为“解释器”的独立程序运行来执行的,该程序通过解释源程序中每条指令的含义来执行它,那么它就会被解释。
术语“动态编程语言”似乎没有正式定义,只是非正式地经常用于指代动态类型语言(即缺少静态类型系统的语言,因此将所有类型检查推迟到运行时)或者是一种编程语言,它能够在运行时实现功能,例如宏、反射、REPL 等。这与程序是否被解释或编译无关。例如,Common Lisp 被认为是一种动态语言,而 OCaml 被认为是一种静态语言(尽管它同时具有宏和 REPL),但解释器和编译器都可用于 Common Lisp 和 OCaml。
还是可以“解释”编译语言?
同样,术语“编译语言”定义不明确。任何语言都可以被解释或编译。形式上,任何可执行语言都可以被解释,并且任何解释器都可以通过对源程序部分特化而变成编译器。
请注意,一些编程语言实现同时使用编译和解释,以获得两全其美的效果。例如,OCaml 可以使用 OCaml 编写的编译器将程序编译为字节码,然后由 C 编写的解释器解释该字节码。这有几个优点:
或者这只是一个语义问题?
术语。
当您说 JavaScript 是“动态的”时,通常是指“动态类型”,这与它通常作为解释语言实现而不是编译的事实无关。“动态类型”的反义词是“静态类型”。请注意,这是一个与“弱类型”和“强类型”描述的属性不同的属性。这两个属性都与解释器与编译器无关,除了几乎总是被解释的脚本语言被动态类型化的趋势。
编译器显然是(嗯,实际上,问题完全是关于充当解释器的编译器,但为了论证的目的,让我们继续吧)不是解释器,所以如果你将一些源代码编译到目标文件中并且执行它,你会认为它显然没有被解释。但事实证明,这不是一条定义非常明确的线。如果您将模拟器视为解释器,那么您可以解释任何可执行文件,无论它最初是什么语言。还有二进制翻译和 JIT 编译器,它们的字节码混淆了一个已经很困惑的问题。但请注意,这里的混淆完全是语义上的,解决方案可能只是一组更新的定义。
相反,您可以通过记录解释器在解释程序时执行的指令并将其作为编译程序回放来“编译”任何解释语言。这不是完全的编译,它不会比解释器更有效,但关键是被解释不是语言的内在品质。
因此,传统上编译的语言可以并且有时被实现为解释语言。那里甚至还有 C 的解释器。我相信这回答了你的问题。我认为关于 F# 的观点是,即使它是交互式的,根据最严格的定义,它也不是一个实际的解释器。这是因为它编译代码位然后运行它们。这并不意味着由于语言的某些属性而无法编写 F# 的严格解释器。
抛开学术争论不谈,与 FSC 编译为可执行文件的代码相比,由 FSI 执行的代码在运行时没有明显的性能下降。在这方面,F# 优于 OCaml -请参阅 Harrop 对 OCaml 顶层的评论。