java 寻求澄清有关弱类型语言的明显矛盾

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9929585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 22:56:41  来源:igfitidea点击:

Seeking clarification on apparent contradictions regarding weakly typed languages

c#javapythonperlweakly-typed

提问by Edwin Dalorzo

I think I understand strong typing, but every time I look for examples for what is weak typing I end up finding examples of programming languages that simply coerce/convert types automatically.

我想我理解强类型,但是每次我寻找弱类型的示例时,我最终都会找到简单地自动强制/转换类型的编程语言示例。

For instance, in this article named Typing: Strong vs. Weak, Static vs. Dynamicsays that Python is strongly typed because you get an exception if you try to:

例如,在这篇名为Typing: Strong vs. Weak, Static vs. Dynamic 的文章中说 Python 是强类型的,因为如果您尝试执行以下操作会得到异常:

Python

Python

1 + "1"
Traceback (most recent call last):
File "", line 1, in ? 
TypeError: unsupported operand type(s) for +: 'int' and 'str'

However, such thing is possible in Java and in C#, and we do not consider them weakly typed just for that.

然而,这种事情在 Java 和 C# 中是可能的,我们不认为它们是弱类型的。

Java

爪哇

  int a = 10;
  String b = "b";
  String result = a + b;
  System.out.println(result);

C#

C#

int a = 10;
string b = "b";
string c = a + b;
Console.WriteLine(c);

In this another article named Weakly Type Languagesthe author says that Perl is weakly typed simply because I can concatenate a string to a number and viceversa without any explicit conversion.

在另一篇名为弱类型语言的文章中,作者说 Perl 是弱类型的,因为我可以将字符串连接到数字,反之亦然,无需任何显式转换。

Perl

珀尔

$a=10;
$b="a";
$c=$a.$b;
print $c; #10a

So the same example makes Perl weakly typed, but not Java and C#?.

所以同一个例子使 Perl 成为弱类型,但不是 Java 和 C#?。

Gee, this is confusing enter image description here

哎呀,这令人困惑 在此处输入图片说明

The authors seem to imply that a language that prevents the application of certain operations on values of different types is strongly typed and the contrary means weakly typed.

作者似乎暗示一种阻止对不同类型的值应用某些操作的语言是强类型的,相反意味着弱类型。

Therefore, at some point I have felt prompted to believe that if a language provides a lot of automatic conversions or coercion between types (as perl) may end up being considered weakly typed, whereas other languages that provide only a few conversions may end up being considered strongly typed.

因此,在某些时候,我觉得有必要相信,如果一种语言提供大量类型之间的自动转换或强制转换(如 perl),最终可能会被认为是弱类型的,而其他只提供少量转换的语言可能最终会被认为是弱类型的。被认为是强类型的。

I am inclined to believe, though, that I must be wrong in this interepretation, I just do not know why or how to explain it.

不过,我倾向于相信,我在这个解释中一定是错误的,我只是不知道为什么或如何解释它。

So, my questions are:

所以,我的问题是:

  • What does it really mean for a language to be truly weakly typed?
  • Could you mention any good examples of weakly typing that are not related to automatic conversion/automatic coercion done by the language?
  • Can a language be weakly typed and strongly typed at the same time?
  • 真正弱类型的语言究竟意味着什么?
  • 您能否提及与该语言所做的自动转换/自动强制无关的弱类型输入的任何好例子?
  • 一种语言可以同时进行弱类型和强类型吗?

回答by Eric Lippert

UPDATE: This question was the subject of my blog on the 15th of October, 2012.Thanks for the great question!

更新:这个问题是我 2012 年 10 月 15 日博客的主题。感谢您提出的好问题!



What does it really mean for a language to be "weakly typed"?

语言“弱类型”到底意味着什么?

It means "this language uses a type system that I find distasteful". A "strongly typed" language by contrast is a language with a type system that I find pleasant.

这意味着“这种语言使用了一种我觉得令人反感的类型系统”。相比之下,“强类型”语言是一种我觉得很愉快的具有类型系统的语言。

The terms are essentially meaningless and you should avoid them. Wikipedialists eleven different meaningsfor "strongly typed", several of which are contradictory. This indicates that the odds of confusion being created are high in any conversation involving the term "strongly typed" or "weakly typed".

这些术语基本上毫无意义,您应该避免使用它们。维基百科列出了“强类型”的十一种不同含义,其中一些是相互矛盾的。这表明在任何涉及“强类型”或“弱类型”的对话中产生混淆的几率都很高。

All that you can really say with any certainty is that a "strongly typed" language under discussion has some additional restriction in the type system, either at runtime or compile time, that a "weakly typed" language under discussion lacks. What that restriction might be cannot be determined without further context.

您真正可以肯定地说,正在讨论的“强类型”语言在类型系统中具有一些额外的限制,无论是在运行时还是编译时,正在讨论的“弱类型”语言都没有。如果没有进一步的背景,就无法确定该限制可能是什么。

Instead of using "strongly typed" and "weakly typed", you should describe in detail what kind of type safety you mean. For example, C# is a statically typedlanguage and a type safelanguage and a memory safelanguage, for the most part. C# allows all three of those forms of "strong" typing to be violated. The cast operator violates static typing; it says to the compiler "I know more about the runtime type of this expression than you do". If the developer is wrong, then the runtime will throw an exception in order to protect type safety. If the developer wishes to break type safety or memory safety, they can do so by turning off the type safety system by making an "unsafe" block. In an unsafe block you can use pointer magic to treat an int as a float (violating type safety) or to write to memory you do not own. (Violating memory safety.)

不要使用“强类型”和“弱类型”,您应该详细描述您的意思是哪种类型安全。例如,C# 是静态类型语言和类型安全语言和内存安全语言,在大多数情况下. C# 允许违反所有这三种形式的“强”类型。cast 运算符违反了静态类型;它对编译器说“我比你更了解这个表达式的运行时类型”。如果开发者出错,那么运行时会抛出异常以保护类型安全。如果开发人员希望破坏类型安全或内存安全,他们可以通过创建“不安全”块来关闭类型安全系统。在不安全的块中,您可以使用指针魔法将 int 视为浮点数(违反类型安全)或写入不属于您的内存。(违反内存安全。)

C# imposes type restrictions that are checked at both compile-time and at runtime, thereby making it a "strongly typed" language compared to languages that do less compile-time checking or less runtime checking. C# also allows you to in special circumstances do an end-run around those restrictions, making it a "weakly typed" language compared with languages which do not allow you to do such an end-run.

C# 强加了在编译时和运行时都进行检查的类型限制,从而使其成为一种“强类型”语言,与编译时检查较少或运行时检查较少的语言相比。C# 还允许您在特殊情况下围绕这些限制进行最终运行,与不允许您执行此类最终运行的语言相比,C# 使其成为“弱类型”语言。

Which is it really? It is impossible to say; it depends on the point of view of the speaker and their attitude towards the various language features.

哪个是真的?不能说;这取决于说话者的观点和他们对各种语言特征的态度。

回答by Ilmari Karonen

As others have noted, the terms "strongly typed" and "weakly typed" have so many different meanings that there's no single answer to your question. However, since you specifically mentioned Perl in your question, let me try to explain in what sense Perl is weakly typed.

正如其他人所指出的,术语“强类型”和“弱类型”有很多不同的含义,因此您的问题没有单一的答案。但是,由于您在问题中特别提到了 Perl,让我尝试解释 Perl 在什么意义上是弱类型的。

The point is that, in Perl, there is no such thing as an "integer variable", a "float variable", a "string variable" or a "boolean variable". In fact, as far as the user can (usually) tell, there aren't even integer, float, string or boolean values: all you have are "scalars", which are all of these things at the same time. So you can, for example, write:

关键是,在 Perl 中,没有“整数变量”、“浮点变量”、“字符串变量”或“布尔变量”这样的东西。事实上,据用户所知(通常),甚至没有整数、浮点数、字符串或布尔:你所拥有的只是“标量”,它们同时是所有这些东西。所以你可以,例如,写:

$foo = "123" + "456";           # $foo = 579
$bar = substr($foo, 2, 1);      # $bar = 9
$bar .= " lives";               # $bar = "9 lives"
$foo -= $bar;                   # $foo = 579 - 9 = 570

Of course, as you correctly note, all of this can be seen as just type coercion. But the point is that, in Perl, types are alwayscoerced. In fact, it's quite hard for a user to tell what the internal "type" of a variable might be: at line 2 in my example above, asking whether the value of $baris the string "9"or the number 9is pretty much meaningless, since, as far as Perl is concerned, those are the same thing. Indeed, it's even possible for a Perl scalar to internally have botha string and a numeric value at the same time, as is e.g. the case for $fooafter line 2 above.

当然,正如您正确指出的那样,所有这些都可以看作只是类型强制。但关键是,在 Perl 中,类型总是被强制的。事实上,用户很难说出变量的内部“类型”可能是什么:在我上面例子的第 2 行,询问 的值$bar是字符串"9"还是数字9几乎毫无意义,因为,如就 Perl 而言,它们是同一回事。事实上,它甚至有可能对于一个Perl标量在内部具有两个字符串,并在同一时间的数值,如,例如的情况下为$foo第2行以后的上方。

The flip side of all this is that, since Perl variables are untyped (or, rather, don't expose their internal type to the user), operators cannot be overloaded to do different things for different types of arguments; you can't just say "this operator will do X for numbers and Y for strings", because the operator can't (won't) tell which kind of values its arguments are.

所有这一切的另一面是,由于 Perl 变量是无类型的(或者,更确切地说,不向用户公开它们的内部类型),操作符不能被重载以对不同类型的参数做不同的事情;你不能只是说“这个运算符将对数字执行 X,对字符串执行 Y”,因为运算符不能(不会)告诉它的参数是哪种值。

Thus, for example, Perl has and needs both a numeric addition operator (+) and a string concatenation operator (.): as you saw above, it's perfectly fine to add strings ("1" + "2" == "3") or to concatenate numbers (1 . 2 == 12). Similarly, the numeric comparison operators ==, !=, <, >, <=, >=and <=>compare the numeric values of their arguments, while the string comparison operators eq, ne, lt, gt, le, geand cmpcompare them lexicographically as strings. So 2 < 10, but 2 gt 10(but "02" lt 10, while "02" == 2). (Mind you, certain otherlanguages, like JavaScript, try to accommodate Perl-like weak typing while alsodoing operator overloading. This often leads to ugliness, like the loss of associativity for +.)

因此,例如,Perl 拥有并需要一个数字加法运算符 ( +) 和一个字符串连接运算符 ( .):正如您在上面看到的,添加字符串 ( "1" + "2" == "3") 或连接数字 ( 1 . 2 == 12) 完全没问题。类似地,数字比较运算符==, !=, <, >, <=, >=and<=>比较其参数的数值,而字符串比较运算符eq, ne, lt, gt, le, geandcmp将它们按字典顺序作为字符串进行比较。所以2 < 10,但是2 gt 10(但是"02" lt 10,同时"02" == 2)。(请注意,某些其他语言,例如 JavaScript,会尝试适应类似 Perl 的弱类型,而也在做运算符重载。这通常会导致丑陋,例如+.)的关联性丢失。)

(The fly in the ointment here is that, for historical reasons, Perl 5 does have a few corner cases, like the bitwise logical operators, whose behavior depends on the internal representation of their arguments. Those are generally considered an annoying design flaw, since the internal representation can change for surprising reasons, and so predicting just what those operators do in a given situation can be tricky.)

(美中不足的是,由于历史原因,Perl 5 确实有一些极端情况,例如按位逻辑运算符,其行为取决于其参数的内部表示。这些通常被认为是一个令人讨厌的设计缺陷,因为内部表示可能会因令人惊讶的原因而改变,因此预测这些运算符在给定情况下的行为可能会很棘手。)

All that said, one could argue that Perl doeshave strong types; they're just not the kind of types you might expect. Specifically, in addition to the "scalar" type discussed above, Perl also has two structured types: "array" and "hash". Those are verydistinct from scalars, to the point where Perl variables have different sigilsindicating their type ($for scalars, @for arrays, %for hashes)1. There arecoercion rules between these types, so you canwrite e.g. %foo = @bar, but many of them are quite lossy: for example, $foo = @barassigns the lengthof the array @barto $foo, not its contents. (Also, there are a few other strange types, like typeglobs and I/O handles, that you don't often see exposed.)

综上所述,人们可能会争辩说 Perl确实有强类型;它们不是您可能期望的那种类型。具体来说,除了上面讨论的“标量”类型,Perl还有两种结构化类型:“数组”和“哈希”。这些是非常从标量不同,到了那里的Perl变量具有不同的点印记,指示它们的类型($用于标量,@数组,%对于散列)1。有这些类型之间的强制规则,这样你就可以写例如%foo = @bar,但其中不少是相当有损耗:例如,$foo = @bar分配长度的数组 @bar$foo,而不是它的内容。(此外,还有一些其他奇怪的类型,例如 typeglobs 和 I/O 句柄,您通常不会看到这些类型。)

Also, a slight chink in this nice design is the existence of reference types, which are a special kind of scalars (and which canbe distinguished from normal scalars, using the refoperator). It's possible to use references as normal scalars, but their string/numeric values are not particularly useful, and they tend to lose their special reference-ness if you modify them using normal scalar operations. Also, any Perl variable2can be blessed to a class, turning it into an object of that class; the OO class system in Perl is somewhat orthogonal to the primitive type (or typelessness) system described above, although it's also "weak" in the sense of following the duck typingparadigm. The general opinion is that, if you find yourself checking the class of an object in Perl, you're doing something wrong.

此外,这个漂亮设计的一个小问题是引用类型的存在,它是一种特殊的标量(并且可以使用ref运算符将其与普通标量区分开来)。可以将引用用作普通标量,但它们的字符串/数字值并不是特别有用,如果您使用普通标量操作修改它们,它们往往会失去其特殊的引用性。此外,任何 Perl 变量2都可以被bless编入一个类,将它变成那个类的对象;Perl 中的 OO 类系统与上面描述的原始类型(或无类型)系统有些正交,尽管它在遵循鸭子类型的意义上也很“弱”范例。一般的观点是,如果您发现自己在 Perl 中检查对象的类,那么您就做错了。



1Actually, the sigil denotes the type of the value being accessed, so that e.g. the first scalar in the array @foois denoted $foo[0]. See perlfaq4for more details.

1实际上,符号表示正在访问的值的类型,因此例如数组中的第一个标量@foo表示为$foo[0]。有关更多详细信息,请参阅perlfaq4

2Objects in Perl are (normally) accessed through references to them, but what actually gets blessed is the (possibly anonymous) variable the reference points to. However, the blessing is indeed a property of the variable, notof its value, so e.g. that assigning the actual blessed variable to another one just gives you a shallow, unblessed copy of it. See perlobjfor more details.

2Perl 中的对象(通常)通过对它们的引用来访问,但实际上得到的bless是引用指向的(可能是匿名的)变量。然而,祝福确实是变量的一个属性,而不是它的值,所以例如,将实际的祝福变量分配给另一个变量只会给你一个浅的、未祝福的副本。有关更多详细信息,请参阅perlobj

回答by Konrad Rudolph

In addition to what Eric has said, consider the following C code:

除了 Eric 所说的,请考虑以下 C 代码:

void f(void* x);

f(42);
f("hello");

In contrast to languages such as Python, C#, Java or whatnot, the above is weakly typed because we losetype information. Eric correctly pointed out that in C# we can circumvent the compiler by casting, effectively telling it “I know more about the type of this variable than you”.

与 Python、C#、Java 或诸如此类的语言相比,上述内容是弱类型的,因为我们丢失了类型信息。Eric 正确地指出,在 C# 中,我们可以通过强制转换来绕过编译器,有效地告诉它“我比你更了解这个变量的类型”。

But even then, the runtime will still check the type! If the cast is invalid, the runtime system will catch it and throw an exception.

但即便如此,运行时仍会检查类型!如果转换无效,运行时系统将捕获它并抛出异常。

With type erasure, this doesn't happen – type information is thrown away. A cast to void*in C does exactly that. In this regard, the above is fundamentally different from a C# method declaration such as void f(Object x).

使用类型擦除,这不会发生——类型信息被丢弃。强制转换为void*用C正是这么做的。在这方面,上述内容与 C# 方法声明(如void f(Object x).

(Technically, C# also allows type erasure through unsafe code or marshalling.)

(从技术上讲,C# 还允许通过不安全代码或编组进行类型擦除。)

Thisis as weakly typed as it gets. Everything else is just a matter of static vs. dynamic type checking, i.e. of the time whena type is checked.

是最弱类型的。其他的一切只是一个静态还是动态类型检查,即时间的事一个类型被选中。

回答by SaulBack

A perfect example comes from the wikipedia article of Strong Typing:

一个完美的例子来自维基百科文章 Strong Typing

Generally strong typing implies that the programming language places severe restrictions on the intermixing that is permitted to occur.

通常强类型意味着编程语言对允许发生的混合设置了严格的限制。

Weak Typing

弱打字

a = 2
b = "2"

concatenate(a, b) # returns "22"
add(a, b) # returns 4

Strong Typing

强打字

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

Notice that a weak typing language can intermix different types without errors. A strong type language requires the input types to be the expected types. In a strong type language a type can be converted (str(a)converts an integer to a string) or cast (int(b)).

请注意,弱类型语言可以混合不同类型而不会出错。强类型语言要求输入类型为预期类型。在强类型语言中,可以转换类型(str(a)将整数转换为字符串)或强制转换( int(b))。

This all depends on the interpretation of typing.

这一切都取决于打字的解释。

回答by Edwin Dalorzo

I would like to contribute to the discussion with my own research on the subject, as others comment and contribute I have been reading their answers and following their references and I have found interesting information. As suggested, it is probable that most of this would be better discussed in the Programmers forum, since it appears to be more theoretical than practical.

我想通过我自己对该主题的研究为讨论做出贡献,因为其他人的评论和贡献我一直在阅读他们的答案并遵循他们的参考资料,我发现了有趣的信息。正如所建议的那样,其中大部分内容可能会在程序员论坛中得到更好的讨论,因为它似乎更具理论性而不是实践性。

From a theoretical standpoint, I think the article by Luca Cardelli and Peter Wegner named On Understanding Types, Data Abstraction and Polymorphismhas one of the best arguments I have read.

从理论的角度来看,我认为 Luca Cardelli 和 Peter Wegner 的文章《关于理解类型、数据抽象和多态性》是我读过的最好的论点之一。

A type may be viewed as a set of clothes (or a suit of armor) that protects an underlying untypedrepresentation from arbitrary or unintended use. It provides a protective covering that hides the underlying representation and constrains the way objects may interact with other objects. In an untyped system untyped objects are nakedin that the underlying representation is exposed for all to see. Violating the type system involves removing the protective set of clothing and operating directly on the naked representation.

类型可以被视为一套衣服(或一套盔甲),它保护底层的无类型表示免于任意或意外使用。它提供了一个保护层,可以隐藏底层表示并限制对象与其他对象交互的方式。在无类型系统中,无类型对象是裸露的,因为底层表示是公开的,所有人都可以看到。违反类型系统涉及脱下防护服并直接在裸体表示上操作。

This statement seems to suggest that weakly typing would let us access the inner structure of a type and manipulate it as if it was something else (another type). Perhaps what we could do with unsafe code (mentioned by Eric) or with c type-erased pointers mentioned by Konrad.

这个陈述似乎表明弱类型可以让我们访问一个类型的内部结构,并把它当作别的东西(另一种类型)来操作。也许我们可以用不安全的代码(Eric 提到的)或 Konrad 提到的 c 类型擦除指针来做些什么。

The article continues...

文章继续……

Languages in which all expressions are type-consistentare called strongly typed languages. If a language is strongly typed its compiler can guarantee that the programs it accepts will execute without type errors. In general, we should strive for strong typing, and adopt static typing whenever possible. Note that every statically typed language is strongly typed but the converse is not necessarily true.

所有表达式都类型一致的语言称为强类型语言。如果一种语言是强类型的,它的编译器可以保证它接受的程序将执行而不会出现类型错误。一般来说,我们应该争取强类型,并尽可能采用静态类型。请注意,每种静态类型语言都是强类型的,但反过来不一定正确。

As such, strong typing means the absence of type errors, I can only assume that weak typing means the contrary: the likely presence of type errors. At runtime or compile time? Seems irrelevant here.

因此,强类型意味着没有类型错误,我只能假设弱类型意味着相反:可能存在类型错误。在运行时还是编译时?在这里似乎无关紧要。

Funny thing, as per this definition, a language with powerful type coercions like Perl would be considered strongly typed, because the system is not failing, but it is dealing with the types by coercing them into appropriate and well defined equivalences.

有趣的是,根据这个定义,像 Perl 这样具有强大类型强制的语言将被认为是强类型的,因为系统没有失败,但它通过将类型强制转换为适当且定义明确的等价来处理类型。

On the other hand, could I say than the allowance of ClassCastExceptionand ArrayStoreException(in Java) and InvalidCastException, ArrayTypeMismatchException(in C#) would indicate a level of weakly typing, at least at compile time? Eric's answer seems to agree with this.

另一方面,我能不能说允许ClassCastExceptionArrayStoreException(在 Java 中)和InvalidCastException, ArrayTypeMismatchException(在 C# 中)表示弱类型级别,至少在编译时?埃里克的回答似乎同意这一点。

In a second article named Typeful Programmingprovided in one of the references provided in one of the answers in this question, Luca Cardelli delves into the concept of type violations:

在第二篇名为Typeful Programming 的文章中,Luca Cardelli 深入研究了类型违规的概念:

Most system programming languages allow arbitrary type violations, some indiscriminately, some only in restricted parts of a program. Operations that involve type violations are called unsound. Type violations fall in several classes [among which we can mention]:

Basic-value coercions: These include conversions between integers, booleans, characters, sets, etc. There is no need for type violations here, because built-in interfaces can be provided to carry out the coercions in a type-sound way.

大多数系统编程语言允许任意类型违规,有些是不分青红皂白的,有些只是在程序的受限部分。涉及类型违规的操作称为不健全的。类型违规分为几类[其中我们可以提到]:

基本值强制转换:包括整数、布尔值、字符、集合等之间的转换。这里不需要类型冲突,因为可以提供内置接口来以类型合理的方式执行强制转换。

As such, type coercions like those provided by operators could be considered type violations, but unless they break the consistency of the type system, we might say that they do not lead to a weakly typed system.

因此,像运算符提供的类型强制可以被视为类型违规,但除非它们破坏类型系统的一致性,否则我们可以说它们不会导致弱类型系统。

Based on this neither Python, Perl, Java or C# are weakly typed.

基于此,Python、Perl、Java 或 C# 都不是弱类型的。

Cardelli mentions two type vilations that I very well consider cases of truly weak typing:

Cardelli 提到了两种类型的 vilations,我很好地考虑了真正弱类型的情况:

Address arithmetic.If necessary, there should be a built-in (unsound) interface, providing the adequate operations on addresses and type conversions. Various situations involve pointers into the heap (very dangerous with relocating collectors), pointers to the stack, pointers to static areas, and pointers into other address spaces. Sometimes array indexing can replace address arithmetic. Memory mapping.This involves looking at an area of memory as an unstructured array, although it contains structured data. This is typical of memory allocators and collectors.

地址算术。如果有必要,应该有一个内置的(不健全的)接口,提供足够的地址和类型转换操作。各种情况包括指向堆的指针(重定位收集器非常危险)、指向堆栈的指针、指向静态区域的指针以及指向其他地址空间的指针。有时数组索引可以代替地址算术。 内存映射。这涉及将内存区域视为非结构化数组,尽管它包含结构化数据。这是典型的内存分配器和收集器。

This kind of things possible in languages like C (mentioned by Konrad) or through unsafe code in .Net (mentioned by Eric) would truly imply weakly typing.

在像 C 这样的语言(由 Konrad 提到)或通过 .Net 中的不安全代码(由 Eric 提到)中可能发生的这种事情真的意味着弱类型。

I believe the best answer so far is Eric's, because the definition of this concepts is very theoretical, and when it comes to a particular language, the interpretations of all these concepts may lead to different debatable conclusions.

我相信到目前为止最好的答案是 Eric 的,因为这些概念的定义非常理论化,当涉及到特定语言时,所有这些概念的解释可能会导致不同的有争议的结论。

回答by user1277476

Weak typing does indeed mean that a high percentage of types can be implicitly coerced, attempting to guess what the coder intended.

弱类型确实意味着可以隐式强制高百分比的类型,试图猜测编码器的意图。

Strong typing means that types are not coerced, or at least coerced less.

强类型意味着类型不被强制,或者至少被强制更少。

Static typing means your variables' types are determined at compile time.

静态类型意味着您的变量类型是在编译时确定的。

Many people have recently been confusing "manifestly typed" with "strongly typed". "Manifestly typed" means that you declare your variables' types explicitly.

许多人最近将“明显类型”与“强类型”混淆了。“明显类型”意味着您显式声明变量的类型。

Python is mostly strongly typed, though you can use almost anything in a boolean context, and booleans can be used in an integer context, and you can use an integer in a float context. It is not manifestly typed, because you don't need to declare your types (except for Cython, which isn't entirely python, albeit interesting). It is also not statically typed.

Python 大多是强类型的,尽管您几乎可以在布尔上下文中使用任何东西,并且可以在整数上下文中使用布尔值,并且可以在浮点上下文中使用整数。它没有明显的类型,因为你不需要声明你的类型(除了 Cython,它不完全是 Python,虽然很有趣)。它也不是静态类型的。

C and C++ are manifestly typed, statically typed, and somewhat strongly typed, because you declare your types, types are determined at compile time, and you can mix integers and pointers, or integers and doubles, or even cast a pointer to one type into a pointer to another type.

C 和 C++ 是明显类型的、静态类型的和有点强类型的,因为你声明你的类型,类型是在编译时确定的,你可以混合整数和指针,或整数和双精度,甚至将指向一种类型的指针转​​换为指向另一种类型的指针。

Haskell is an interesting example, because it is not manifestly typed, but it's also statically and strongly typed.

Haskell 是一个有趣的例子,因为它没有明显类型,但它也是静态和强类型的。

回答by Antti Haapala

The strong <=> weak typing is not only about the continuum on how much or how little of the values are coerced automatically by the language for one datatype to another, but how strongly or weakly the actual valuesare typed. In Python and Java, and mostly in C#, the values have their types set in stone. In Perl, not so much - there are really only a handful of different valuetypes to store in a variable.

强 <=> 弱类型不仅是关于语言将一种数据类型的值的多少或多少自动强制转换为另一种数据类型的连续统,还涉及实际的类型强或弱。在 Python 和 Java 中,主要是在 C# 中,值的类型是固定不变的。在 Perl 中,没有那么多——实际上只有少数不同的值类型可以存储在变量中。

Let's open the cases one by one.

让我们一一打开案例。



Python

Python

In Python example 1 + "1", +operator calls the __add__for type intgiving it the string "1"as an argument - however, this results in NotImplemented:

在 Python 示例中1 + "1"+运算符调用__add__for 类型int将字符串"1"作为参数 - 但是,这会导致 NotImplemented:

>>> (1).__add__('1')
NotImplemented

Next, the interpreter tries the __radd__of str:

接下来,解释器尝试__radd__str 的:

>>> '1'.__radd__(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'

As it fails, the +operator fails with the the result TypeError: unsupported operand type(s) for +: 'int' and 'str'. As such, the exception does not say much about strong typing, but the fact that the operator +does not coerceits arguments automatically to the same type, is a pointer to the fact that Python is not the most weakly typed language in the continuum.

当它失败时,+运算符失败并返回结果TypeError: unsupported operand type(s) for +: 'int' and 'str'。因此,异常并没有说明强类型,但运算符+不会自动将其参数强制为相同类型这一事实表明 Python 不是连续体中最弱类型的语言。

On the other hand, in Python 'a' * 5isimplemented:

另一方面,在 Python 中'a' * 5是这样实现的:

>>> 'a' * 5
'aaaaa'

That is,

那是,

>>> 'a'.__mul__(5)
'aaaaa'

The fact that the operation is different requires some strong typing - however the opposite of *coercing the values to numbers before multiplying still would not necessarily make the values weakly typed.

操作不同的事实需要一些强类型 - 但是*在乘法之前将值强制转换为数字的相反仍然不一定会使值弱类型。



Java

爪哇

The Java example, String result = "1" + 1;works only because as a fact of convenience, the operator +is overloaded for strings. The Java +operator replaces the sequence with creating a StringBuilder(see this):

Java 示例String result = "1" + 1;之所以有效,只是因为为方便起见,该运算符+已为字符串重载。Java+运算符将序列替换为创建 a StringBuilder(请参阅):

String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()

This is rather an example of very static typing, without no actual coercion - StringBuilderhas a method append(Object)that is specifically used here. The documentation says the following:

这是一个非常静态的类型的例子,没有实际的强制 -StringBuilder有一个append(Object)专门用于这里的方法。文档说明如下:

Appends the string representation of the Objectargument.

The overall effect is exactly as if the argument were converted to a string by the method String.valueOf(Object), and the characters of that string were then appended to this character sequence.

附加Object参数的字符串表示形式。

整体效果就像参数被方法转换为String.valueOf(Object)字符串,然后将该字符串的字符附加到该字符序列。

Where String.valueOfthen

String.valueOf那么在哪里

Returns the string representation of the Object argument. [Returns] if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString()is returned.

返回 Object 参数的字符串表示形式。[返回] 如果参数是null,则字符串等于"null"; 否则,obj.toString()返回的值。

Thus this is a case of absolutely no coercion by the language - delegating every concern to the objects itself.

因此,这是一个绝对没有语言强制的情况 - 将所有关注委托给对象本身。



C#

C#

According to the Jon Skeet answer here, operator +is not even overloaded for the stringclass - akin to Java, this is just convenience generated by the compiler, thanks to both static and strong typing.

根据这里Jon Skeet 回答,运算符+甚至没有为string类重载- 类似于 Java,这只是编译器生成的便利,这要归功于静态类型和强类型。



Perl

珀尔

As the perldataexplains,

正如perldata解释的那样,

Perl has three built-in data types: scalars, arrays of scalars, and associative arrays of scalars, known as "hashes". A scalar is a single string (of any size, limited only by the available memory), number, or a reference to something (which will be discussed in perlref). Normal arrays are ordered lists of scalars indexed by number, starting with 0. Hashes are unordered collections of scalar values indexed by their associated string key.

Perl 具有三种内置数据类型:标量、标量数组和标量关联数组,称为“散列”。标量是单个字符串(任意大小,仅受可用内存限制)、数字或对某物的引用(将在 perlref 中讨论)。普通数组是按数字索引的有序标量列表,从 0 开始。哈希是由其关联字符串键索引的标量值的无序集合。

Perl however does not have a separate data type for numbers, booleans, strings, nulls, undefineds, references to other objects etc - it just has one type for these all, the scalar type; 0 is a scalar value as much as is "0". A scalar variablethat was set as a string can really change into a number, and from there on behave differently from "just a string", if it is accessed in a numerical context. The scalar can hold anything in Perl, it is as much the object as it exists in the system. whereas in Python the names just refers to the objects, in Perl the scalar values in the names are changeable objects. Furthermore, the Object Oriented Type system is glued on top of this: there are just 3 datatypes in perl - scalars, lists and hashes. A user defined object in Perl is a reference (that is a pointer to any of the 3 previous) blessed to a package - you can take any such value and bless it to any class at any instant you want.

然而,Perl 对于数字、布尔值、字符串、空值、undefineds、对其他对象的引用等没有单独的数据类型——它只有一种类型,标量类型;0 是与“0”一样多的标量值。被设置为字符串的标量变量可以真正变成一个数字,如果在数字上下文中访问它那么它的行为就与“只是一个字符串”不同. Perl 中的标量可以容纳任何东西,它是系统中存在的对象。而在 Python 中,名称仅指代对象,而在 Perl 中,名称中的标量值是可变对象。此外,面向对象类型系统紧贴于此:perl 中只有 3 种数据类型——标量、列表和散列。Perl 中的用户定义对象是对包的引用(即指向前 3 个中的任何一个的指针)bless- 您可以采用任何此类值并在您想要的任何时刻将其祝福给任何类。

Perl even allows you to change the classes of values at whim - this is not possible in Python where to create a value of some class you need to explicitly construct the value belonging to that class with object.__new__or similar. In Python you cannot really change the essence of the object after the creation, in Perl you can do much anything:

Perl 甚至允许您随心所欲地更改值的类 - 这在 Python 中是不可能的,其中创建某个类的值,您需要显式构造属于该类的值object.__new__或类似的值。在 Python 中,您无法在创建后真正改变对象的本质,而在 Perl 中,您可以做很多事情:

package Foo;
package Bar;

my $val = 42;
# $val is now a scalar value set from double
bless $val, Foo;
# all references to $val now belong to class Foo
my $obj = $val;
# now $obj refers to the SV stored in $val
# thus this prints: Foo=SCALAR(0x1c7d8c8)
print $val, "\n"; 
# all references to $val now belong to class Bar
bless $val, Bar;
# thus this prints Bar=SCALAR(0x1c7d8c8)
print $val, "\n";
# we change the value stored in $val from number to a string
$val = 'abc';
# yet still the SV is blessed: Bar=SCALAR(0x1c7d8c8)
print $val, "\n";
# and on the course, the $obj now refers to a "Bar" even though
# at the time of copying it did refer to a "Foo".
print $obj, "\n";

thus the type identity is weakly bound to the variable, and it can be changed through any reference on the fly. In fact, if you do

因此类型标识与变量弱绑定,并且可以通过任何引用动态更改。事实上,如果你这样做

my $another = $val;

\$anotherdoes not have the class identity, even though \$valwill still give the blessed reference.

\$another没有阶级身份,即使还是\$val会给出祝福的参考。



TL;DR

TL; 博士

There are much more about weak typing to Perl than just automatic coercions, and it is more about that the types of the values themselves are not set into stone, unlike the Python which is dynamically yet very strongly typed language. That python gives TypeErroron 1 + "1"is an indication that the language is strongly typed, even though the contrary one of doing something useful, as in Java or C# does not preclude them being strongly typed languages.

Perl 的弱类型不仅仅是自动强制,而且更多的是值本身的类型不是一成不变的,这与 Python 不同,Python 是动态但非常强类型的语言。这蟒蛇给人TypeError1 + "1"是一种迹象表明,语言是强类型,即使做一些有用的一个相反,如Java或C#不排除他们是强类型语言。

回答by Jan Steinman

As many others have expressed, the entire notion of "strong" vs "weak" typing is problematic.

正如许多其他人所表达的那样,“强”与“弱”类型的整个概念是有问题的。

As a archetype, Smalltalk is very strongly typed -- it will alwaysraise an exception if an operation between two objects is incompatible. However, I suspect few on this list would call Smalltalk a strongly-typed language, because it is dynamically typed.

作为一个原型,Smalltalk 是非常强类型的——如果两个对象之间的操作不兼容,它总是会引发异常。但是,我怀疑这个列表中很少有人会将 Smalltalk 称为强类型语言,因为它是动态类型的。

I find the notion of "static" versus "dynamic" typing more useful than "strong" versus "weak." A statically-typed language has all the types figured out at compile-time, and the programmer has to explicitly declare if otherwise.

我发现“静态”与“动态”类型的概念比“强”与“弱”更有用。静态类型语言具有在编译时确定的所有类型,否则程序员必须显式声明。

Contrast with a dynamically-typed language, where typing is performed at run-time. This is typically a requirement for polymorphic languages, so that decisions about whether an operation between two objects is legal does not have to be decided by the programmer in advance.

与动态类型语言相比,在运行时执行类型。这通常是多态语言的要求,因此关于两个对象之间的操作是否合法的决定不必由程序员事先决定。

In polymorphic, dynamically-typed languages (like Smalltalk and Ruby), it's more useful to think of a "type" as a "conformance to protocol." If an object obeys a protocol the same way another object does -- even if the two objects do not share any inheritance or mixins or other voodoo -- they are considered the same "type" by the run-time system. More correctly, an object in such systems is autonomous, and can decide if it makes sense to respond to any particular message referring to any particular argument.

在多态、动态类型的语言(如 Smalltalk 和 Ruby)中,将“类型”视为“协议的一致性”更为有用。如果一个对象以与另一个对象相同的方式遵守协议——即使这两个对象不共享任何继承或混合或其他巫术——它们被运行时系统视为相同的“类型”。更准确地说,此类系统中的对象是自治的,并且可以决定响应引用任何特定参数的任何特定消息是否有意义。

Want an object that can make some meaningful response to the message "+" with an object argument that describes the colour blue? You can do that in dynamically-typed languages, but it is a pain in statically-typed languages.

想要一个对象可以对消息“+”做出一些有意义的响应,并使用描述蓝色的对象参数?您可以在动态类型的语言中做到这一点,但在静态类型的语言中却很痛苦。

回答by Lubo Antonov

I like @Eric Lippert's answer, but to address the question - strongly typed languages typically have explicit knowledge of the types of variables at each point of the program. Weakly typed languages do not, so they can attempt to perform an operation that may not be possible for a particular type. It think the easiest way to see this is in a function. C++:

我喜欢@Eric Lippert 的回答,但为了解决这个问题 - 强类型语言通常对程序每个点的变量类型都有明确的了解。弱类型语言不会,因此它们可以尝试执行特定类型可能无法执行的操作。它认为查看这一点的最简单方法是在函数中。C++:

void func(string a) {...}

The variable ais known to be of type string and any incompatible operation will be caught at compile time.

该变量a已知为字符串类型,任何不兼容的操作都将在编译时被捕获。

Python:

Python:

def func(a)
  ...

The variable acould be anything and we can have code that calls an invalid method, which will only get caught at runtime.

变量a可以是任何东西,我们可以有调用无效方法的代码,该方法只会在运行时被捕获。