Weak Typing.
接下来我们再来介绍一个语言概念,strongly typed language 与 weakly typed language。
首先要强调,语言的强/弱类型与静态/动态类型是没有必然联系的两个概念。ML 与 Racket 虽然分别采用静态与动态类型系统,但它们都可被视为是强类型语言。
对于想要阻止的问题 X,不同的语言有不同的处理方式:
- static checking: 利用 static checker 在 compile-time 检出。
- dynamic checking: 若 static checker 无法检出 X (语言不使用 static checker 或其 static checker 对问题 X 是 unsound 的),则在语言实现中加入一些 dynamic checks 在 run-time 阻止 X 发生。
- ……
- weak typing: 语言实现根本不对程序进行检查:认定 X 的出现是程序员本身的问题。若程序员本身没有发现问题,X 将会发生。(你程序员觉得是我的锅,那就是我的锅)
C/C++ 是很典型的弱类型语言:举一个非常熟悉的例子,C/C++ 中的数组越界问题。即使我们访问了不合法的数组下标如 a[-1],C/C++ 也不会阻止程序的运行,最后程序可能会因为访问某些未申请的内存而导致崩溃。
所谓强类型语言,就是其类型系统 (type system) 中存在较多的 restrictions,阻止潜在 bug 程序的运行。而弱类型语言的 restrictions 就相对较少。
相对于强类型语言,弱类型语言省去了进行检查的时间成本,存储数据 (例如 dynamic checks 所需要记录的 tags 信息) 的空间成本;但所付出的代价是,程序的 bug 更需要程序员本身进行检出而不能依靠强类型语言中的各种检查来发现。(相信我们都遇到过出现难以 de 出的奇怪 bug,最后发现是数组越界的抓狂时刻)
因此,在实际应用中存在很多外置的 checking tools 对弱类型语言程序进行检查;这是一个折中的方案。
另外需要强调的是,语言的强/弱类型比起是一种定义,不如说是一种相对的概念,具体可以参考这个帖子,回答者讲的很好。在中文语境下对强/弱类型似乎还有另外的定义,与变量的定义与类型转换规则相关。
Extended Semantics
对于某个想要避免的问题 X,一些语言并不纠结是否将其检出的问题,它们选择扩展其 primitives 的语义。例如,传统的 + 只允许两个数字进行相加,一个 string 类型的参数是不合法的。
而在 Python 中,"Hello" + "World" 这样的表达是合法的;这是因为 Python 扩展了 + 的 semantics,使其具有了连接两个 string 类型字符串的语义。
关于是否将问题 X 所对应的本来应当视作 bug 的语句赋予新的意义这个问题见仁见智:一方面,这样的处理使得一些 bug 更难被检出。一方面,它又确实给程序员带来了很多方便。
Reference
Supplementary notes:
My notes in CnBlogs. My implementation.
Is C# a strongly typed or weakly typed language?.
Course info:
Programming Languages, Part B, University of Washington, Lecturer: Professor Dan Grossman.