对于静态表达不充分的语言,匈牙利符号是否可以解决?[关闭]


28

在埃里克·利珀特(Eric Lippert)的文章中,匈牙利表示法是怎么回事?,他指出,匈牙利符号(一种好符号)的目的是为了

扩展“类型”的概念以涵盖除存储表示信息之外的语义信息。

一个简单的示例是,用x表示变量的前缀是x,用y表示变量的前缀是y,无论这些变量是整数还是浮点数或其他形式,这样当您不小心编写时xFoo + yBar,代码显然看起来是错误的。

但是我也一直在阅读有关Haskell的类型系统的信息,似乎在Haskell中,可以使用编译器会为您检查的实际类型来完成同一件事(即“将类型的概念扩展为包含语义信息”)。因此,在上面的示例中,xFoo + yBar如果正确设计程序,在Haskell中实际上将无法编译,因为它们将被声明为不兼容的类型。换句话说,Haskell的类型系统似乎有效地支持了相当于匈牙利表示法的编译时检查。

那么,匈牙利符号法是否只是一种编程语言的创可贴,其类型系统无法对语义信息进行编码?还是匈牙利记谱法提供的东西超出了Haskell的静态类型系统所能提供的东西?

(当然,我以Haskell为例。我确定还有其他语言具有类似表现力(丰富?强?)类型系统,尽管我还没有遇到过。)


明确地说,我不是在用数据类型注释变量名,而是在程序上下文中使用有关变量含义的信息。例如,变量可以是整数,浮点数,双精度或长整数等,但变量的含义可能是它是以英寸为单位的相对x坐标。这就是我所说的通过匈牙利表示法(和通过Haskell类型)编码的信息。


Pascal-尽管如果您尝试添加在Pascal中定义的XCood和YCoord类型,则只会收到一个编译器警告IIRC
mcottle

1
blog.moertel.com/articles/2006/10/18/…是一篇有关在Haskell的类型系统中执行与“ apps hungarian”非常相似的操作的文章。
Logan Capaldo

1
F#也具有此样式功能。
Rangoric

那是一个非常不错的文章链接(moertel.com链接),准确地显示了我正在考虑的事情:使用类型系统将字符串插值安全漏洞等转化为编译时错误。感谢您的链接。
瑞安·汤普森

我认为很多OO都赶上了匈牙利的语义符号,因为今天您可能会写:Foo.Position.X + Bar.Position.Y。
Pieter B'6

Answers:


27

我会说“是”。

如您所说,匈牙利表示法的目的是将信息编码为无法在类型中编码的名称。但是,基本上有两种情况:

  1. 该信息很重要。
  2. 该信息并不重要。

让我们首先从情况2开始:如果该信息不重要,那么匈牙利表示法就是多余的噪音。

更为有趣的情况是数字1,但我认为如果信息很重要,则应对其进行检查,即它应该是类型的一部分,而不是名称

这使我们回到了埃里克·利珀特的名言:

扩展“类型”的概念以涵盖除存储表示信息之外的语义信息。

实际上,这不是“扩展类型的概念”,而是类型的概念!类型(作为设计工具)的全部目的是对语义信息进行编码!存储表示是一个实现细节,通常不会在类型属于可言。(特别是在OO语言中不能属于该类型,因为表示独立性是OO的主要先决条件之一。)


匈牙利符号最常使用AFAIK的C语言不是OO语言。
彼得Török

4
@PéterTörök:OO是一种设计模式,不是语言的功能,尽管现代语言旨在简化C而没有。
1月Hudec

3
@PéterTörök:我用纯C语言编写了很多面向对象的代码。我确实知道我在说什么。
Jan Hudec

1
重要的信息应该嵌入变量的类型而不是其名称中,这确实是正确的,但是有许多重要的事情要说,但是系统不能表达哪种类型。例如,if S1是Universe中唯一引用char[],其持有人可以并且将在需要时更改它,但绝不能暴露于外部代码,并且S2是对char[]任何人都不应更改但可以共享的的引用。对于承诺不改变它的对象,应该S1并且S2在语义上应被视为相同的“事物”?
2014年

1
@supercat-您正在描述唯一性类型。
杰克

9

类型(作为设计工具)的全部目的是对语义信息进行编码!

我喜欢这个答案,并想跟进这个答案...

我对Haskell一无所知,但是您可以xFoo + yBar使用任何支持某种类型的类型安全的语言(例如C,C ++或Java)来完成类似的示例。在C ++中,您可以使用只接受自己类型的对象的重载“ +”运算符来定义XDir和YDir类。在C或Java中,您需要使用add()函数/方法(而不是“ +”运算符)进行加法。

我一直看到匈牙利符号用于类型信息,而不是语义(除非语义可能由类型表示)。一种方便的方式,可以在“智能”编程编辑器出现之前记住变量的类型,这些编辑器可以在编辑器中以一种或多种方式为您显示类型。


面向对象既不是必需的,也不是一种允许xFoo + yBar用户定义类型的语言所必需的,对于使该示例正常工作,C ++的OO方面也不是必需的。
卢克·丹顿

您是对的,不是OO,而是类型安全。我编辑了答案。
BHS

嗯 很好的一点是,您几乎可以xFoo + yBar使用任何一种语言进行编译错误(或至少是运行时错误)。但是,在Java或C ++中使用XDir和YDir类进行数学运算会比使用原始数字进行数学运算慢吗?我的理解是,在Haskell中,类型是在编译时检查的,然后在运行时检查的,这只是原始数学运算,没有类型检查,因此不比添加常规数字慢。
瑞安·汤普森

在C ++中,类型检查也将在编译时完成,并且在大多数情况下,转换等操作都将被优化。Java也不能做到这一点,因为它不允许运算符重载,因此,例如,您不能将an XCoordinate视为常规int。
2011年

5

我意识到,“匈牙利符号”一词的含义与原始词有所不同,但我会回答“否”。用语义或计算类型命名变量与SML或Haskell样式键入的功能不同。它甚至不是创可贴。以C为例,您可以命名一个变量gpszTitle,但是该变量可能没有全局作用域,它甚至不能构成以空值结尾的字符串的指向。

我认为,更现代的匈牙利符号与强大的类型推导系统的差异更大,因为它们将“语义”信息(例如“ g”用于全局或“ f”用于标志)与计算类型(“ p”指针, i“整数等。)这只是一个邪恶的混乱,变量名与它们的计算类型只是模糊的相似(随时间变化),并且看起来都非常相似,以至于您不能使用“ next match”来在特定函数中找到变量-它们都是相同的。


4

匈牙利符号是为BCPL发明的,BCPL是完全没有类型的语言。确切地说,它只有一种数据类型,即单词。单词可以是指针,也可以是字符,布尔值或纯整数,具体取决于您使用的方式。显然,这很容易造成可怕的错误,例如取消引用角色。因此,发明了匈牙利表示法,以便程序员至少可以通过查看代码来执行手动类型检查。

C是BCPL的后代,具有不同的整数,指针,字符等类型。这在某种程度上使匈牙利的基本符号变得多余(如果是int或指针,则无需使用变量名进行编码),但是超出此级别的语义仍无法表示为类型。这导致匈牙利语被称为“系统”和“应用程序”之间的区别。您无需表示变量是int,但可以使用代码字母来指示int是x还是y坐标或索引。

更现代的语言允许自定义类型的定义,这意味着您可以在类型中而不是变量名中编码语义约束。例如,典型的OO语言将具有特定的坐标对和区域类型,因此避免将x坐标添加到y坐标。

例如,在Joels 赞美Apps Hungarian的著名文章中,他将前缀示例us用于不安全的字符串和s安全的(HTML编码的)字符串,以防止HTML注入。开发人员可以通过简单地仔细检查代码并确保变量前缀匹配来防止HTML注入错误。他的示例使用的是VBScript,这是一种过时的语言,最初不允许自定义类。用现代语言可以用自定义类型解决问题,而这确实是Asp.net对HtmlString类所做的事情。这样,编译器将自动发现错误,这比依靠人眼更安全。因此很明显,在这种情况下,具有自定义类型的语言消除了对“ Apps匈牙利语”的需求。


2

是的,尽管许多具有足够强大的类型系统的语言仍然存在问题-基于/类似于现有类型的新类型的可表达性。

也就是说,在许多语言环境中,我们可以更多地使用类型系统,因为这样做是因为创建一个与名称之外的类型基本相同的新类型(除了名称和几个转换函数)的开销太大。

本质上,我们需要某种强类型的typedef来彻底杀死这些语言中的匈牙利符号(F#风格的UoM也可以做到)


2

请记住,曾经有一段时间IDE没有弹出提示来告诉您变量的类型是什么。曾经有一段时间,IDE不了解他们正在编辑的代码,因此您不能轻易地从使用过渡到声明。还有一段时间,如果不手动浏览整个代码库就无法重构变量名,请手动进行更改并希望您不会错过任何一个。您无法使用搜索和替换功能,因为搜索客户还会获得CustomerName ...

在那段黑暗的日子里,了解变量在何处使用是什么类型很有帮助。如果维护得当(由于缺乏重构工具,则为BIG),匈牙利符号为您提供了这一点。

这些天来,它产生的可怕名称的成本太高了,但这是相对较新的事情。仍然有很多代码早于我描述的IDE开发。


1
如果我没记错的话,这是另一个答案,它针对的是与OP要求的匈牙利符号不同的匈牙利符号。
2011年

2
此答案描述了所谓的“系统匈牙利语”,其中前缀表示语言级别的“类型”。该问题询问“ Apps Hungarian”,其中“ type”一词未被误解,表示语义类型。如今,系统匈牙利人几乎受到普遍谴责(正确的是,这是匈牙利概念真正目的的混蛋)。但是,Apps Hungarian可能是一件好事。
2011年

自70年代以来,已经存在能够搜索sCustomer而不选择sCustomerName(vi和emacs是两个示例)的编辑器。
拉里·科尔曼

@Larry,也许,但是您不能让它们在我80年代编程的系统上运行
mcottle

@cHAo,不,不是-我的意思是试图解释为什么人们通常将额外的信息放入变量名中。我故意避免提及任何形式的匈牙利符号。也许我在“为什么搜索和替换无法在源代码上工作”部分中给出的示例看起来像“ Systems Hungarian”,但这并不是故意的。为了避免混淆,我删除了前导“ s”。
mcottle

0

正确!

在诸如汇编程序之类的完全非类型化语言之外,匈牙利表示法是多余且令人讨厌的。令人怀疑的是,当您考虑到大多数IDE在键入时都会检查类型安全性。

多余的“ i”,“ d”和“?” 前缀只会使代码的可读性降低,并且可能确实会产生误导-就像当“牛人”将iaSumsItems的类型从“整数”更改为“长整数”时一样,而不会费心重构字段名。


9
您的回答表明您不了解原始的,聪明的“ Apps”匈牙利语与愚蠢的混蛋(称为“ Systems”匈牙利语)之间的区别。阅读joelonsoftware.com/articles/Wrong.html
Ryan Culpepper
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.