正如其他人所指出的那样,术语“强类型”和“弱类型”具有许多不同的含义,因此您的问题没有单一的答案。但是,既然您在问题中特别提到了Perl,那么让我试着解释一下Perl在什么意义上是弱类型的。
关键是,在Perl中,没有“整数变量”,“浮点变量”,“字符串变量”或“布尔变量”这样的东西。事实上,就用户(通常)所能分辨的而言,甚至没有整数,浮点数,字符串或布尔值:你所拥有的只是“标量”,它们同时是所有这些东西。因此,例如,您可以编写:
$foo = "123" + "456"; # $foo = 579
$bar = substr($foo, 2, 1); # $bar = 9
$bar .= " lives"; # $bar = "9 lives"
$foo -= $bar; # $foo = 579 - 9 = 570
当然,正如您正确指出的那样,所有这些都可以被视为只是类型强制。但关键是,在Perl中,类型总是被强制的。事实上,用户很难分辨变量的内部“类型”可能是什么:在上面的示例的第2行,询问的值是字符串还是数字几乎毫无意义,因为就Perl而言,这些是一回事。事实上,Perl 标量甚至可能在内部同时具有字符串和数值,例如上面第 2 行之后的情况。$bar
"9"
9
$foo
所有这一切的另一面是,由于Perl变量是非类型化的(或者更确切地说,不向用户公开其内部类型),因此运算符不能重载以对不同类型的参数执行不同的事情;你不能只是说“这个运算符将对数字执行X,对字符串执行Y”,因为运算符不能(不会)告诉其参数是哪种值。
因此,例如,Perl 具有并且需要一个数字加法运算符 () 和一个字符串串联运算符 ():如您上面所见,添加字符串 () 或连接数字 () 是完全可以的。类似地,数值比较运算符 、 、 、 和 比较其参数的数值,而字符串比较运算符 、 、 、 和 将它们作为字符串进行字典比较。所以,但是(但是,虽然)。(请注意,某些其他语言,如JavaScript,尝试适应类似Perl的弱类型,同时也进行运算符重载。这通常会导致丑陋,就像失去联想性一样。+
.
"1" + "2" == "3"
1 . 2 == 12
==
!=
<
>
<=
>=
<=>
eq
ne
lt
gt
le
ge
cmp
2 < 10
2 gt 10
"02" lt 10
"02" == 2
+
(这里美中不足的是,由于历史原因,Perl 5确实有一些极端情况,比如按位逻辑运算符,其行为取决于其参数的内部表示。这些通常被认为是一个令人讨厌的设计缺陷,因为内部表示可能会因为令人惊讶的原因而改变,因此预测这些运算符在给定情况下的作用可能很棘手。
综上所述,有人可能会说Perl确实有强类型;它们只是不是你所期望的那种类型。具体来说,除了上面讨论的“标量”类型之外,Perl还有两种结构化类型:“数组”和“哈希”。这些与标量非常不同,以至于Perl变量具有不同的sigil来指示它们的类型(对于标量,对于数组,对于哈希)1。这些类型之间有强制规则,因此您可以编写例如 ,但其中许多都是非常有损的:例如,将数组的长度分配给 ,而不是其内容。(此外,还有其他一些奇怪的类型,如typeglobs和I / O句柄,您通常不会看到暴露。$
@
%
%foo = @bar
$foo = @bar
@bar
$foo
此外,在这个漂亮的设计中,一个轻微的缺点是存在引用类型,它们是一种特殊的标量(并且可以使用运算符与普通标量区分开来)。可以将引用用作普通标量,但它们的字符串/数值并不是特别有用,如果使用正常的标量操作修改它们,它们往往会失去其特殊的引用性。此外,任何Perl变量2都可以被转换为一个类,将其转换为该类的对象;Perl中的OO类系统与上面描述的原始类型(或无类型)系统有些正交,尽管它在遵循鸭子类型范式的意义上也是“弱”的。普遍的看法是,如果你发现自己在Perl中检查了一个对象的类,那么你做错了什么。ref
bless
1 实际上,sigil表示被访问的值的类型,因此例如,数组中的第一个标量表示。有关更多详细信息,请参阅 perlfaq4。@foo
$foo[0]
Perl中的2个对象(通常)是通过对它们的引用来访问的,但实际上得到的是引用指向的(可能是匿名的)变量。然而,祝福确实是变量的属性,而不是它的价值,所以例如,将实际的祝福变量分配给另一个变量只会给你一个浅薄的,不祝福的副本。有关更多详细信息,请参阅 perlobj。bless