Edw*_*rzo 176 c# python java perl weakly-typed
我想我理解强类型,但每次我查找弱类型的例子时,我最终会找到编程语言的例子,这些语言只是自动强制/转换类型.
例如,在本文中名为Typing:Strong vs. Weak,Static vs. Dynamic表示Python是强类型的,因为如果你试图:
蟒蛇
1 + "1"
Traceback (most recent call last):
File "", line 1, in ?
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Run Code Online (Sandbox Code Playgroud)
但是,在Java和C#中这样的事情是可能的,我们并不认为它们只是因为弱类型.
Java的
int a = 10;
String b = "b";
String result = a + b;
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)
C#
int a = 10;
string b = "b";
string c = a + b;
Console.WriteLine(c);
Run Code Online (Sandbox Code Playgroud)
在另一篇名为Weakly Type Languages的文章中,作者说Perl是弱类型的,因为我可以将字符串连接到数字而反之亦然,而不进行任何显式转换.
Perl的
$a=10;
$b="a";
$c=$a.$b;
print $c; #10a
Run Code Online (Sandbox Code Playgroud)
所以同样的例子使得Perl弱类型,但不是Java和C#?
哎呀,这很令人困惑 
作者似乎暗示,阻止对不同类型的值应用某些操作的语言是强类型的,而相反意味着弱类型.
因此,在某些时候我感到有提示相信,如果一种语言提供了大量的自动转换或类型之间的强制(如perl)可能最终被认为是弱类型,而其他只提供少量转换的语言可能最终会被被认为是强类型的.
但我倾向于相信,在这种解释中我一定是错的,我只是不知道为什么或如何解释它.
所以,我的问题是:
Eri*_*ert 209
更新:这个问题是我的博客在2012年10月15日的主题.感谢您提出的好问题!
对于一种"弱类型"的语言来说,它真正意味着什么?
这意味着"这种语言使用了一种我觉得令人反感的类型系统".相比之下,"强类型"语言是一种具有我觉得愉快的类型系统的语言.
这些术语基本上没有意义,你应该避免使用它们.维基百科列出了"强类型"的11种不同含义,其中有几种是矛盾的.这表明在涉及术语"强类型"或"弱类型"的任何对话中产生混淆的可能性很高.
所有你能确切地说的是,正在讨论的"强类型"语言在类型系统中有一些额外的限制,无论是在运行时还是在编译时,讨论中的"弱类型"语言都缺乏.如果没有进一步的背景,就无法确定这种限制.
您应该详细描述您所说的类型安全性,而不是使用"强类型"和"弱类型".例如,C#是一种静态类型语言,大多数情况下是类型安全语言和内存安全语言.C#允许违反所有这三种"强"类型.强制类型操作符违反静态类型; 它对编译器说"我比你更了解这个表达式的运行时类型".如果开发人员错了,那么运行时将抛出异常以保护类型安全.如果开发人员希望打破类型安全或内存安全,他们可以通过制作"不安全"块来关闭类型安全系统.在不安全的块中,您可以使用指针魔法将int视为浮点(违反类型安全)或写入您不拥有的内存.(违反记忆安全.)
C#强加了在编译时和运行时检查的类型限制,从而使其成为一种"强类型"语言,与编译时检查较少或运行时检查较少的语言相比.C#还允许您在特殊情况下对这些限制进行最终运行,使其成为一种"弱类型"语言,而不允许您进行此类终止运行的语言.
这到底是哪个?不可能说; 这取决于发言者的观点以及他们对各种语言特征的态度.
Ilm*_*nen 64
正如其他人所指出的那样,"强类型"和"弱类型"这两个术语有很多不同的含义,因此对你的问题没有单一的答案.但是,既然您在问题中特别提到了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
Run Code Online (Sandbox Code Playgroud)
当然,正如你所正确指出的那样,所有这些都可以看作只是类型强制.但问题是,在Perl中,类型总是被强制执行.实际上,用户很难分辨出变量的内部"类型"是什么:在我上面的例子的第2行,询问值$bar是字符串"9"还是数字9几乎没有意义,因为,就Perl而言,这些都是一回事.实际上,Perl标量甚至可以在内部同时具有字符串和数值,例如$foo上面第2行之后的情况.
所有这一切的另一面是,因为Perl变量是无类型的(或者更确切地说,不向用户公开它们的内部类型),所以不能重载运算符来为不同类型的参数做不同的事情; 你不能只说"这个运算符将为数字执行X而对于字符串执行Y",因为运算符不能(不会)告诉它的参数是哪种值.
因此,例如,Perl具有并且需要数字加法运算符(+)和字符串连接运算符(.):如上所述,添加字符串("1" + "2" == "3")或连接数字(1 . 2 == 12)是完全正确的.同样,数字比较操作符==,!=,<,>,<=,>=并<=>比较它们的参数的数值,而字符串比较操作符eq,ne,lt,gt,le,ge和cmp字典顺序比较它们为字符串.所以2 < 10,但是2 gt 10(但是"02" lt 10,同时"02" == 2).(请注意,某些其他语言,如JavaScript,尝试适应类似Perl的弱类型,同时还要进行操作符重载.这通常会导致丑陋,就像失去关联性一样+.)
(美中不足的是,由于历史原因,Perl 5确实有一些极端情况,如按位逻辑运算符,其行为取决于其参数的内部表示.这些通常被认为是一个恼人的设计缺陷,因为内部表示可以出于令人惊讶的原因而改变,因此预测这些操作员在给定情况下所做的事情可能很棘手.)
总而言之,人们可以说Perl 确实有很强的类型; 它们不是你所期望的那种类型.具体来说,除了上面讨论的"标量"类型之外,Perl还有两种结构化类型:"数组"和"哈希".这些与标量非常不同,直到Perl变量具有不同的符号来指示它们的类型($对于标量,@对于数组,%对于散列)1.有有这些类型之间的强制规则,这样你就可以写例如%foo = @bar,但其中不少是相当有损耗:例如,$foo = @bar分配长度的数组 @bar来$foo,而不是其内容.(另外,还有一些其他奇怪的类型,比如typeglobs和I/O句柄,你经常看不到它们.)
此外,这个漂亮设计的一个微小的缺点是引用类型的存在,它是一种特殊的标量(并且可以使用ref运算符区分普通标量).可以将引用用作普通标量,但它们的字符串/数值不是特别有用,如果使用常规标量操作修改它们,它们往往会丢失它们的特殊引用.此外,任何Perl变量2都可以bless编辑为一个类,将其转换为该类的对象; Perl中的OO类系统与上述的原始类型(或无类型)系统有些正交,尽管在遵循鸭子打字范例的意义上它也是"弱"的.一般的观点是,如果您发现自己在Perl中检查对象的类,那么您做错了.
1实际上,sigil表示被访问的值的类型,因此例如@foo表示数组中的第一个标量$foo[0].有关详细信息,请参阅perlfaq4.
2 Perl中的对象(通常)通过对它们的引用来访问,但实际获得的bless是引用所指向的(可能是匿名的)变量.然而,祝福确实是变量的属性,而不是它的值,所以例如,将实际的祝福变量分配给另一个只是给你一个浅的,未经过复制的变量.有关详细信息,请参阅perlobj.
Kon*_*lph 19
除了Eric所说的,还要考虑以下C代码:
void f(void* x);
f(42);
f("hello");
Run Code Online (Sandbox Code Playgroud)
与Python,C#,Java或诸如此类的语言相比,上面的类型很弱,因为我们丢失了类型信息.Eric正确地指出,在C#中,我们可以通过强制转换来绕过编译器,有效地告诉它"我知道这个变量的类型比你更多".
但即便如此,运行时仍将检查类型!如果强制转换无效,运行时系统将捕获它并抛出异常.
对于类型擦除,这不会发生 - 类型信息被丢弃.强制转换为void*用C正是这么做的.在这方面,上述内容与C#方法声明根本不同,例如void f(Object x).
(从技术上讲,C#还允许通过不安全的代码或编组进行类型擦除.)
这就是它的弱类型.其他的一切只是一个静态与动态类型检查的事情,即时间,当一个类型被选中.
Sau*_*ack 14
一个完美的例子来自维基百科强力打字文章:
通常,强类型意味着编程语言对允许发生的混合施加严格的限制.
打字薄弱
a = 2
b = "2"
concatenate(a, b) # returns "22"
add(a, b) # returns 4
Run Code Online (Sandbox Code Playgroud)
强大的打字
a = 2
b = "2"
concatenate(a, b) # Type Error
add(a, b) # Type Error
concatenate(str(a), b) #Returns "22"
add(a, int(b)) # Returns 4
Run Code Online (Sandbox Code Playgroud)
请注意,弱类型语言可以混合使用不同类型而不会出错.强类型语言要求输入类型为预期类型.在强类型语言中,可以转换类型(str(a)将整数转换为字符串)或转换(int(b)).
这一切都取决于打字的解释.
| 归档时间: |
|
| 查看次数: |
11587 次 |
| 最近记录: |