解释器和静态类型检查
Intepreters and static type checking
看完这篇post:
How does an interpreter/compiler work
我有这个问题:
在只有解释器的编程语言中(例如Basic)(如上面第二个答案中的照片link)是否可以进行静态类型检查??。
据我所知,解释器 运行 每次我们执行程序时,每个单行命令。那么在我们 运行 程序之前如何静态地检查类型呢??
语言就是语言,既不解释也不编译,until is.意思是,同一种语言可以即时解释or 可以编译成二进制文件。事实上,解释器确实会将运行中的代码编译成字节码。
编译型语言和解释型语言之间的主要区别在于,解释型程序需要单独的 运行 时间,而编译型程序通常可以 运行 自己或使用最少的 bootstrap 帮助从操作系统。编译器通常也会比解释器在编译步骤上花费更多的时间,它可以进行更深入的错误检查和代码优化。口译员不这样做只是因为它是一个缓慢的过程,而不是因为它根本不可能。
Type hints/inference 是一个完全独立的问题。许多主要编译的语言广泛使用类型提示,因为编译器有时间使用该信息。主要解释型语言通常会放弃类型提示,因为额外的类型检查会花费时间 at 运行time,并且语言的设计目标是快速开发周期开始,这包括更少的打字。这并不意味着这些语言无论如何都是 "type free",每个值仍然具有 类型 ,并且该类型是已知的.事实上,如今甚至许多编译语言在不必要的简洁时也会放弃显式类型注释。例如:
Foo foo = new Foo();
let foo = new Foo();
这里的 Foo
类型提示是多余的;当然,编译器可以推断 foo
是 Foo
类型,只需查看赋值的右侧即可。这同样适用于任何其他类型,包括数字、字符串等。编译器或静态类型分析器可以跟踪哪些值被分配给变量或从函数返回什么值,并推断出很多关于类型的信息,而无需一个显式注释。
话虽如此,在严重依赖 运行时间信息的未注释语言中,在某些情况下,不可能知道变量的类型,直到 运行时间。在那种情况下,静态类型分析器或编译器无法提前提供帮助,也无法在编译时捕获因类型不兼容而导致的错误。例如,TypeScript 是 Javascript 的静态类型的附加解决方案,它走那条线。您在 TypeScript 中所做 注释的所有内容都经过严格的类型检查;您所做的任何 不 注释或保留为 any
都无法进行类型检查,并且 可能 在 运行 处炸毁您的脸时间.
静态类型语言和动态类型语言中的类型系统有不同的用途(注意静态与动态类型,不是 "compiled" 与 "interpreted")。静态类型主要用于在编译时捕获错误并为编译器提供更多信息以生成更好的代码;动态类型用于定义 程序行为 ,即两种类型的值在操作时应如何表现,其中包括在不兼容的类型上抛出错误。即使不是在所有情况下,静态分析器仍然可以预测此类不兼容的类型错误。
通常说静态类型的编程语言是类型检查的 "at compile time",所以说 "interpreters don't have a compile time1 and therefore can't be statically typed" 可能很容易,但实际上 "static" 并不一定意味着"at compile time",表示"before run time"或"without running the code".
因此,静态类型语言是一种程序中任何地方的类型错误都会导致程序无法 运行 的语言。而在动态类型语言中,类型错误只会在控制流到达错误类型的语句时中止执行。
那么,根据这个定义,是否可以使用解释器来实现静态类型语言?当然。只需让解释器在程序开始执行任何内容之前发现程序中的类型错误(使用编译器将使用的相同算法),瞧,你就有了静态类型检查。
您可能不想这样做的原因是它会增加启动时间,因为它在代码开始执行之前引入了一个额外的步骤。并且根据类型系统的复杂性,类型检查实际上可能会消耗大量时间。所以这对口译员来说可能会很烦人,但这绝对是可能的。
1 这只适用于非常简单的解释器。大多数现实世界的解释器都涉及一些代码生成,无论是字节码还是 JITed 机器码。
看完这篇post:
How does an interpreter/compiler work
我有这个问题:
在只有解释器的编程语言中(例如Basic)(如上面第二个答案中的照片link)是否可以进行静态类型检查??。
据我所知,解释器 运行 每次我们执行程序时,每个单行命令。那么在我们 运行 程序之前如何静态地检查类型呢??
语言就是语言,既不解释也不编译,until is.意思是,同一种语言可以即时解释or 可以编译成二进制文件。事实上,解释器确实会将运行中的代码编译成字节码。
编译型语言和解释型语言之间的主要区别在于,解释型程序需要单独的 运行 时间,而编译型程序通常可以 运行 自己或使用最少的 bootstrap 帮助从操作系统。编译器通常也会比解释器在编译步骤上花费更多的时间,它可以进行更深入的错误检查和代码优化。口译员不这样做只是因为它是一个缓慢的过程,而不是因为它根本不可能。
Type hints/inference 是一个完全独立的问题。许多主要编译的语言广泛使用类型提示,因为编译器有时间使用该信息。主要解释型语言通常会放弃类型提示,因为额外的类型检查会花费时间 at 运行time,并且语言的设计目标是快速开发周期开始,这包括更少的打字。这并不意味着这些语言无论如何都是 "type free",每个值仍然具有 类型 ,并且该类型是已知的.事实上,如今甚至许多编译语言在不必要的简洁时也会放弃显式类型注释。例如:
Foo foo = new Foo();
let foo = new Foo();
这里的 Foo
类型提示是多余的;当然,编译器可以推断 foo
是 Foo
类型,只需查看赋值的右侧即可。这同样适用于任何其他类型,包括数字、字符串等。编译器或静态类型分析器可以跟踪哪些值被分配给变量或从函数返回什么值,并推断出很多关于类型的信息,而无需一个显式注释。
话虽如此,在严重依赖 运行时间信息的未注释语言中,在某些情况下,不可能知道变量的类型,直到 运行时间。在那种情况下,静态类型分析器或编译器无法提前提供帮助,也无法在编译时捕获因类型不兼容而导致的错误。例如,TypeScript 是 Javascript 的静态类型的附加解决方案,它走那条线。您在 TypeScript 中所做 注释的所有内容都经过严格的类型检查;您所做的任何 不 注释或保留为 any
都无法进行类型检查,并且 可能 在 运行 处炸毁您的脸时间.
静态类型语言和动态类型语言中的类型系统有不同的用途(注意静态与动态类型,不是 "compiled" 与 "interpreted")。静态类型主要用于在编译时捕获错误并为编译器提供更多信息以生成更好的代码;动态类型用于定义 程序行为 ,即两种类型的值在操作时应如何表现,其中包括在不兼容的类型上抛出错误。即使不是在所有情况下,静态分析器仍然可以预测此类不兼容的类型错误。
通常说静态类型的编程语言是类型检查的 "at compile time",所以说 "interpreters don't have a compile time1 and therefore can't be statically typed" 可能很容易,但实际上 "static" 并不一定意味着"at compile time",表示"before run time"或"without running the code".
因此,静态类型语言是一种程序中任何地方的类型错误都会导致程序无法 运行 的语言。而在动态类型语言中,类型错误只会在控制流到达错误类型的语句时中止执行。
那么,根据这个定义,是否可以使用解释器来实现静态类型语言?当然。只需让解释器在程序开始执行任何内容之前发现程序中的类型错误(使用编译器将使用的相同算法),瞧,你就有了静态类型检查。
您可能不想这样做的原因是它会增加启动时间,因为它在代码开始执行之前引入了一个额外的步骤。并且根据类型系统的复杂性,类型检查实际上可能会消耗大量时间。所以这对口译员来说可能会很烦人,但这绝对是可能的。
1 这只适用于非常简单的解释器。大多数现实世界的解释器都涉及一些代码生成,无论是字节码还是 JITed 机器码。