无论在编译语言中键入(静态还是动态),编译期间不是都会捕获所有错误吗?
Aren't all errors caught during compilation regardless of typing (static vs. dynamic) in a compiled language?
下面是一个answer explaining Dynamic vs. Static Typing.
我很困惑为什么这演示了动态类型和静态类型,因为我认为编译语言的所有错误无论如何都会在编译过程中被捕获,所以它是静态类型还是动态类型都没有关系。
也许这表明静态类型语言总是在 运行 之前引发错误,而动态类型总是在执行期间引发错误,无论它是编译还是解释?
有人可以更深入地解释一下吗?
Here is an example contrasting how Python (dynamically typed) and Go
(statically typed) handle a type error:
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
Python does type checking at run time, and therefore:
silly(2)
Runs perfectly fine, and produces the expected output Hi
. Error is only raised if the problematic line is hit:
silly(-1)
Produces
TypeError: unsupported operand type(s) for +: 'int' and 'str'
因为实际执行了相关行
另一方面,Go 在编译时进行类型检查:
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
以上编译不通过,报错如下:
invalid operation: "3" + 5 (mismatched types string and int)
编译<->解释量表与动态<->静态类型量表完全正交。 (可能还有另一个编译时类型检查和运行时间类型检查的正交尺度)
例如,您可以使用 Cython 将示例中的 Python 脚本编译为本机二进制文件。它将以完全相同的方式工作,但它将被编译。 Python 脚本也可以使用 mypy
提前进行类型检查,并使用 CPython 进行 运行,它提供 运行 时间类型异常。
另一方面,您可以安装一种具有静态类型和交互式 shell(解释器)的语言,并在代码执行之前尝试类似的表达式 - you'll get a type error。这部分有点令人困惑,因为要得到类型错误,你需要在某种程度上编译代码(处理成 AST 并进行类型检查),但我认为它不符合 "compiled" 的常见定义。
总而言之,您可以进行动态类型编译、静态编译、动态类型解释和静态类型解释。 (repl 中的链接示例可以说是关于强类型的——请随时提供更好的类型)
没有。除非语言是静态类型的,否则编译时不会捕获类型错误。
请注意,无论键入什么,编译都会捕获语法错误。
这个例子令人困惑,因为它将 "Static & Compiled" 与 "Dynamic & Interpreted" 结合在一起,这掩盖了不同类型系统的影响。
- Go 示例如果是 动态类型 就不会抛出错误,尽管已编译!
- Python 示例如果是 静态类型 将抛出错误,即使该行永远不会被解释!
类型检查与正在编译或解释的语言无关!
我将复习基本概念,然后深入研究示例。
编译与解释
"When source code is translated"
- 源代码:原始代码(通常由人输入计算机)
- 翻译:将源代码转换为计算机可以读取的内容(即机器代码)
- 运行-Time:程序执行命令的时间段(编译后,如果编译)
- 编译语言:在运行-时间
之前翻译的代码
- 解释型语言:代码在执行期间即时翻译
正在打字
"When types are checked"
5 + '3'
是 强类型 语言(例如 Go 和 Python)中类型错误的示例,因为它们不允许 "type coercion" -> 值在特定上下文中更改类型的能力,例如合并两种类型。 弱类型 语言,例如 JavaScript,不会抛出类型错误(导致 '53'
)。
- 静态:运行-时间
之前检查的类型
- 动态:在执行期间即时检查类型
"Static & Compiled" 和 "Dynamic & Interpreted" 的定义非常相似...但请记住它是 "when types are checked" 与 "when source code is translated"。
无论语言是编译型还是解释型,您都会遇到相同类型的错误!您需要在概念上区分这些术语。
Python 例子
动态,解释
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
silly(2)
因为 Python 是解释型和动态类型型的,它只翻译和类型检查它正在执行的代码。 else
块永远不会执行,所以 5 + '3'
甚至都不会被查看!
如果是静态类型呢?
甚至在代码 运行 之前就会抛出类型错误。即使它被解释,它仍然在 运行 时间之前执行类型检查。
编译出来了怎么办?
else
块在 运行 之前会是 translated/looked,但因为它是动态类型的,所以不会抛出错误!动态类型语言在执行之前不检查类型,并且该行永远不会执行。
Go 示例
静态,已编译
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
在 运行ning(静态)之前检查类型并立即捕获类型错误!如果对类型进行解释,仍会在 运行 时间之前检查类型,结果相同。如果它是动态的,即使在编译期间会查看代码,它也不会抛出任何错误。
性能
如果编译语言是静态类型的(相对于动态类型),它在 运行 时会有更好的性能;类型知识允许机器代码优化。
静态类型语言在 运行 时间本质上具有更好的性能,因为在执行时不需要动态检查类型(它在 运行ning 之前检查)。
同样,编译语言在 运行 时速度更快,因为代码已经被翻译,而不需要即时 "interpret"/翻译它。
请注意,编译语言和静态类型语言在翻译和类型检查之前 运行 会有延迟。
更多差异
静态类型会及早捕获错误,而不是在执行过程中发现它们(对长程序特别有用)。它更 "strict" 因为它不允许程序中任何地方出现类型错误,并且通常会阻止变量更改类型,从而进一步防止意外错误。
num = 2
num = '3' // ERROR
动态类型更灵活,有些人对此表示赞赏。它通常允许变量更改类型,这可能会导致意外错误。
下面是一个answer explaining Dynamic vs. Static Typing.
我很困惑为什么这演示了动态类型和静态类型,因为我认为编译语言的所有错误无论如何都会在编译过程中被捕获,所以它是静态类型还是动态类型都没有关系。
也许这表明静态类型语言总是在 运行 之前引发错误,而动态类型总是在执行期间引发错误,无论它是编译还是解释?
有人可以更深入地解释一下吗?
Here is an example contrasting how Python (dynamically typed) and Go (statically typed) handle a type error:
def silly(a): if a > 0: print 'Hi' else: print 5 + '3'
Python does type checking at run time, and therefore:
silly(2)
Runs perfectly fine, and produces the expected output
Hi
. Error is only raised if the problematic line is hit:silly(-1)
Produces
TypeError: unsupported operand type(s) for +: 'int' and 'str'
因为实际执行了相关行
另一方面,Go 在编译时进行类型检查:
package main import ("fmt" ) func silly(a int) { if (a > 0) { fmt.Println("Hi") } else { fmt.Println("3" + 5) } } func main() { silly(2) }
以上编译不通过,报错如下:
invalid operation: "3" + 5 (mismatched types string and int)
编译<->解释量表与动态<->静态类型量表完全正交。 (可能还有另一个编译时类型检查和运行时间类型检查的正交尺度)
例如,您可以使用 Cython 将示例中的 Python 脚本编译为本机二进制文件。它将以完全相同的方式工作,但它将被编译。 Python 脚本也可以使用 mypy
提前进行类型检查,并使用 CPython 进行 运行,它提供 运行 时间类型异常。
另一方面,您可以安装一种具有静态类型和交互式 shell(解释器)的语言,并在代码执行之前尝试类似的表达式 - you'll get a type error。这部分有点令人困惑,因为要得到类型错误,你需要在某种程度上编译代码(处理成 AST 并进行类型检查),但我认为它不符合 "compiled" 的常见定义。
总而言之,您可以进行动态类型编译、静态编译、动态类型解释和静态类型解释。 (repl 中的链接示例可以说是关于强类型的——请随时提供更好的类型)
没有。除非语言是静态类型的,否则编译时不会捕获类型错误。
请注意,无论键入什么,编译都会捕获语法错误。
这个例子令人困惑,因为它将 "Static & Compiled" 与 "Dynamic & Interpreted" 结合在一起,这掩盖了不同类型系统的影响。
- Go 示例如果是 动态类型 就不会抛出错误,尽管已编译!
- Python 示例如果是 静态类型 将抛出错误,即使该行永远不会被解释!
类型检查与正在编译或解释的语言无关!
我将复习基本概念,然后深入研究示例。
编译与解释
"When source code is translated"
- 源代码:原始代码(通常由人输入计算机)
- 翻译:将源代码转换为计算机可以读取的内容(即机器代码)
- 运行-Time:程序执行命令的时间段(编译后,如果编译)
- 编译语言:在运行-时间 之前翻译的代码
- 解释型语言:代码在执行期间即时翻译
正在打字
"When types are checked"
5 + '3'
是 强类型 语言(例如 Go 和 Python)中类型错误的示例,因为它们不允许 "type coercion" -> 值在特定上下文中更改类型的能力,例如合并两种类型。 弱类型 语言,例如 JavaScript,不会抛出类型错误(导致 '53'
)。
- 静态:运行-时间 之前检查的类型
- 动态:在执行期间即时检查类型
"Static & Compiled" 和 "Dynamic & Interpreted" 的定义非常相似...但请记住它是 "when types are checked" 与 "when source code is translated"。
无论语言是编译型还是解释型,您都会遇到相同类型的错误!您需要在概念上区分这些术语。
Python 例子
动态,解释
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
silly(2)
因为 Python 是解释型和动态类型型的,它只翻译和类型检查它正在执行的代码。 else
块永远不会执行,所以 5 + '3'
甚至都不会被查看!
如果是静态类型呢?
甚至在代码 运行 之前就会抛出类型错误。即使它被解释,它仍然在 运行 时间之前执行类型检查。
编译出来了怎么办?
else
块在 运行 之前会是 translated/looked,但因为它是动态类型的,所以不会抛出错误!动态类型语言在执行之前不检查类型,并且该行永远不会执行。
Go 示例
静态,已编译
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
在 运行ning(静态)之前检查类型并立即捕获类型错误!如果对类型进行解释,仍会在 运行 时间之前检查类型,结果相同。如果它是动态的,即使在编译期间会查看代码,它也不会抛出任何错误。
性能
如果编译语言是静态类型的(相对于动态类型),它在 运行 时会有更好的性能;类型知识允许机器代码优化。
静态类型语言在 运行 时间本质上具有更好的性能,因为在执行时不需要动态检查类型(它在 运行ning 之前检查)。
同样,编译语言在 运行 时速度更快,因为代码已经被翻译,而不需要即时 "interpret"/翻译它。
请注意,编译语言和静态类型语言在翻译和类型检查之前 运行 会有延迟。
更多差异
静态类型会及早捕获错误,而不是在执行过程中发现它们(对长程序特别有用)。它更 "strict" 因为它不允许程序中任何地方出现类型错误,并且通常会阻止变量更改类型,从而进一步防止意外错误。
num = 2
num = '3' // ERROR
动态类型更灵活,有些人对此表示赞赏。它通常允许变量更改类型,这可能会导致意外错误。