为什么语言相对于块的显式标记为什么要缩进?


11

我正在学习Haskell,并且正在寻找一种自动缩进工具。我看上去并不多,并且了解到在Haskell中(与Python中一样),缩进表示一个块。结果,我猜想不可能创建一个像C系列其他语言一样强大的自动格式化工具,该工具使用显式标记,例如{}(大括号)或begin end关键字。

我不介意为了缩进而强制执行缩进的语言,但是我无法理解强制缩进和具有一些显式标记所带来的好处,以便自动化工具可以理解哪个块属于哪个块。

如果缩进标记的优先选择是使代码看起来更好,那么我仍然不了解其优势。假定制表符和空格在不同的编辑器和不同的字体(例如,单空格字体看起来更整齐)中以不同的方式表示,那么期望程序员像样地呈现代码是不可行的。可以考虑当前文本编辑器的工具将更适合于正确设置代码格式。

语言设计师为什么会选择缩进而不是显式的块标记?


8
没有一个答案,但哈斯克尔使空白灵敏度很多比Python更可选。您可以对大多数内容使用分号,并根据需要将大括号括起来。let x =1; y = 2; z = 3是完全有效的do { putStrLn $ show x; putStrLn $ show y; putStrLn $ show z; }。那些不必在同一行。
KChaloux

8
“不可能创建自动格式化工具”-实际上,由于缩进规则,因此在Python中不需要这种自动格式化工具。
布朗

13
嗯,增加缩进一个明确的块标记。
Karl Bielefeldt

3
@ K.Gkinis:语言设计者本身就是寻求语言设计决定的确切动机的最佳来源。
罗伯特·哈维

3
这个问题实际上不是主观的。它询问为什么一些语言设计师选择某种语法。这可以回答。如果问题询问哪种语法最好,那将是主观的。
JacquesB

Answers:


13

吉多·冯·罗苏姆(Guido Von Rossum)

与吉多·范罗苏姆接受记者采访时,可在全文中可以看出与books.google.com(重点煤矿):

选择缩进进行分组在Python中并不是一个新颖的概念。我是从ABC继承过来的,但是它也发生在较旧的语言occam中。我不知道ABC的作者是从occam那里得到这个想法,还是独立发明了它,或者是否有一个共同的祖先。当然,我可以选择不遵循ABC的领导,就像我在其他领域所做的那样(例如,ABC使用大写字母表示语言关键字和过程名称,我没有复制过这个想法),但是我相当喜欢此功能在使用ABC时花了一点时间,因为它似乎消除了当时C用户之间关于在何处放置花括号的某种毫无意义的争论

冯·罗苏姆(Von Rossum)受ABC的极大启发,尽管他不必复制所有内容,但缩进的使用得以保留,因为它可以避免宗教战争。

我也很清楚,可读代码无论如何自愿使用缩进来表示分组,并且在代码中我遇到了一些细微的错误,即缩进与使用花括号的句法分组不一致 -程序员和任何审阅者都认为缩进与分组匹配因此没有注意到该错误。同样,一个漫长的调试会议也教了宝贵的一课。

Rossum还目睹了由于分组和缩进之间的不一致而导致的错误,并且显然,尽管仅依靠缩进来构造代码会更安全,从而避免编程错误1

Donald E. Knuth和Peter J.Landin

在引用的采访中,Guido提到了Don Knuth使用缩进的想法。这在详细的克努特缩进报价重新发现,它的报价结构化程序设计与GOTO语句。Knuth还引用了Peter John Landin的“下700种编程语言”(请参阅有关缩进的“讨论”部分)。Landin设计的ISWIM看起来像是带有缩进的第一语言,而不是开始/结束块。这些论文更多地是关于使用缩进来构造程序的可行性,而不是赞成这样做的实际论据。


1.我认为这实际上是一个论点,它赞成同时具有分组构造和自动格式化的功能,以便捕捉并从必将发生的编程错误中恢复过来。如果您使用Python压缩缩进,那么调试代码的人将不得不猜测哪个是正确的:

if (test(x)):
  foo(x)
  bar(x)

bar始终调用还是仅在测试成功的情况下调用?

分组构造增加了一定程度的冗余,可帮助您在自动缩进代码时发现错误。在C语言中,等效代码可以如下自动缩进:

if (test(x))
  foo(x);
bar(x);

如果我打算bar与处于同一级别foo,那么基于代码结构的自动缩进让我看到可以通过在foo和周围添加大括号来解决某些错误bar

在《Python:关于缩进的神话》中,有一个C的错误示例:

/*  Warning:  bogus C code!  */

if (some condition)
        if (another condition)
                do_something(fancy);
else
        this_sucks(badluck);

与上面的情况相同,在Emacs中,我突出显示整个块/功能,按Tab,然后重新缩进所有代码。人的缩进和代码结构之间的差异告诉我,有些地方不对(那和前面的评论!)。

此外,在C中缩进关闭的中间代码根本无法通过master分支来完成,所有适当的样式检查都会使GCC / Jenkins对我大叫。最近,我遇到了一个与上面在Python中描述的问题类似的问题,只是缩进了一层。有时候,我用C语言编写的代码超出了括号的范围,但是后来我打了Tab键,代码缩进了“错误地”:那是再一次看到bug的机会。


3
“为避免宗教战争……”令我惊讶的是,真正的原因如此微不足道。
罗伯特·哈维

1
@RobertHarvey:对这一短语的强调是通过coredump,而不是van Rossum。这不是在上下文中阅读van Rossum报价的主要原因。
JacquesB

@JacquesB请告诉我报价中缺少什么上下文,以便我编辑答案。
coredump

4
不过,我没有得到您的个人评论:如果您在Python中加紧缩进,那么您就有一个bug。如果您用C拧大括号,那么您将遇到错误。如果您使用自动缩进,则两种语言都完全相同。而且,如果您不使用自动缩进功能,则可以使用Python不可能的方式将错误隐藏在C中。
JacquesB '16

2
@JacquesB,因为您正在积极地输入右括号;缩进不足是您可能会忘记做的事情。当然,您可能会忘记在适当的时间合上支架,但是最终您将不得不这样做,并且有另一个机会来考虑它。我认为python对初学者来说效果很好,因为它迫使人们注意缩进。
marstato

7

这是非常主观的,并且是许多火焰战争的原因。然而:

用符号界定块缩进符违反了DRY原理,因为您以两种不同的方式表示相同的信息。自动缩进工具的存在是这种DRY违规的征兆:可以自动生成缩进表明它是冗余信息,这意味着缩进和符号可能不同步,从而导致误导代码。

Python 设计和历史常见问题明确指出了这一点:

为什么Python将缩进用于语句分组?

Guido van Rossum认为使用缩进进行分组非常优雅,并且为普通Python程序的清晰度做出了很大贡献。一段时间后,大多数人学会了爱上此功能。

由于没有开始/结束括号,因此在解析器和人类读者所感知的分组之间不会存在分歧。

的确,您不能为Python创建自动缩进工具,但这是一件好事:这意味着您在语法上没有多余之处,因此您不需要自动化工具来进行协调。

制表符与空格在Python中是一个合理的考虑,建议不要在同一代码库中混用制表符和空格(用于缩进)。

Python从(现在已经过时的)前身语言ABC继承了重要的缩进形式。ABC是使用可用性测试指导设计的极少数编程语言之一。因此,尽管有关语法的讨论通常归结于主观意见和个人喜好,但选择有效的缩进实际上具有更坚实的基础。


6
重复记帐也违反了DRY。冗余有时是一个功能。
coredump

3
@coredump:是的,但这是故意设计的冗余。包括Python在内的大多数编程语言都包含故意选择的冗余-例如pass可以自动推断出的关键字,但要求将其明确表示有助于发现错误。同时具有开头/结尾符号(对于编译器)和缩进(对于人类读者)的偶然冗余似乎导致了比捕获的错误更多的错误。至少这似乎是范·罗森的观点。
JacquesB

@coredump-现在我知道为什么我不是会计师。
JeffO

3
@coredump您也想念COBOL PROCEDURE DIVISION.吗?我永远无法说出DATA DIVISION这些新奇语言的目的和过程在哪里开始。
msw 16

2
@coredump:“看到缩进与我所想到的足以抵制错误,这是对的”。
JacquesB '16

2

语言设计师之所以选择语法上重要的空格,是因为他们认为(或至少认为其潜在用户相信)空格,大括号在阅读代码时会增加噪音,从而损害了生产力。另一个常见的原因是不良/不一致的编码风格会损害可读性-通过强制使用通用的缩进方案,该语言总体上具有更好的可读性。既然自动格式化IDE更为普遍,但后来的原因就不那么重要了,但仍然可以应用。


1
我明白为什么人们会考虑分号和花括号噪音。但是,必须输入4/8/12倍的空间是否会降低生产力?而且,如果您错过了一个(因为它们不可见),那么您就会遇到麻烦。
恢复莫妮卡

5
这就是为什么您使用制表符而不是空格,或使用IDE来了解如何将制表符转换为四个空格的块的原因。
罗伯特·哈维

@ K.Gkinis:缩进不是不可见的。只有行尾的空白是不可见的,但这在任何语言中都不重要。只有混合使用制表符和空格,您才会遇到麻烦。所以不要那样做。
JacquesB '16

@JacquesB:缩进的可见性/隐蔽性的问题在于,作为人类,您通常无法分辨空格和制表符之间的区别,而计算机却可以并且通常可以分辨出来。因此,当缩进可见时,计算机解释缩进的方式可能会有所不同。那才是真正的问题:当计算机对待隐形字符的方式不同于对人类的对待时。人类以屏幕上的距离来衡量缩进,计算机可以以文字的数量来衡量缩进。 那是看不见的部分。
布莱恩·奥克利

@BryanOakley:是的,这就是为什么您不应该在缩进中混用制表符和空格。
JacquesB '16
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.