为什么Pascal控件结构看起来不一致?

时间:2011-01-06 23:58:46

标签: delphi language-design pascal freepascal

大多数Pascal控件结构对我有意义,例如:

for ... do {statement};

if (condition) then {statement};

while (condition) do {statement};

其中{statement}是单个语句,或开始 ... 结束块。我有一个问题:

repeat {statement-list} until (expression);

try {statement-list} except {statement-list} end;

重复尝试具有相同的一般结构,仅接受单个语句或开始,这不是更好吗? 。结束阻止,而不是一个没有正式阻止开始结束的陈述列表?

7 个答案:

答案 0 :(得分:9)

需要开始/结束的表单都存在于一行中 - 编译器没有其他方法可以知道块结束的位置。不需要开头/结尾的表单有一个结束结构,告诉编译器结束的位置,因此开始/结束只是多余的。如果你愿意,你可以在这种情况下自由使用它。

答案 1 :(得分:8)

Niklaus Wirth(Pascal的设计师)用他的下一个语言Modula-2纠正了这些不一致。在Modula-2中,IF等复合语句没有BEGIN和强制END

IF {condition} THEN
    {statement-list}
END;

其他控制结构(例如WHILE)与REPEAT类似且一致。

答案 2 :(得分:5)

问题是:难道不是更好吗?

答案是:这取决于,因为这种事情完全是主观的。除非你是一台机器,否则就像机器一样。

是的,它会满足一些对于强制执行所有复合语句的开始/结束的一致性,但是如果周围的语言元素已经提供了一个自然的外壳,那么要求它是完全多余的。

考虑CASE声明:

// "Sensible" syntax

  case VALUE of
    1: DoSomething;
    2: begin
         DoSomethingElse;
         DoMore;
       end;
  else
    DoForAllOtherValues;
    DoMore;
  end;

与一个不太明智但更一致和“合乎逻辑”的对比:

  case VALUE of
    1: DoSomething;
    2: begin
         DoSomethingElse;
         DoMore;
       end;
  else
    begin
      DoForAllOtherValues;
      DoMore;
    end;
  end;

请注意,最终的“结束”是“案例”的一部分。你不能没有它。

我很确定在Chrome的早期版本(后来成为Oxygene和随后的Prism)中,这实际上是case语句的必需语法。如果是这样,情况就不再如此。常识大概占了上风。

在我个人看来,满足OGoSC(目标神的句法一致性)会激怒或许更小,但实际上与你和我更相关,SGoHRaC(人类可读性和理解的主观神)。

虽然在许多情况下它可能看起来不同,但我们人类实际上并不是机器。我们不需要将规则简化并简化为最小一致集,以便能够解析文本并理解它。我们需要一些规则,但我们可以处理更多,因为我们对机器的巨大优势是思想自由,使我们摆脱严格的语法和结构方案,特别是在这种语法和结构与冗余点无关的情况下。 p>

就像在这种情况下一样。

如果你犯了编译器无法解释的错误,它会在每次编译时告诉你。但编译器不会感谢你使代码“更容易”“读取”(编译器只是遵循它给出的规则 - 它不会让编译器“更容易”通过更改“读取”代码它已经可以非常愉快地遵循的规则了。)

如果你强加任意规则使其更难阅读(不是因为规则或多或少不变/一致,而是因为你强加了一个一致的结构,其本身包含更多的噪音和必须过滤的冗余信息)那么你将为人类的生产力付出代价。

事实上,这些“更容易”更“一致”的规则实际上可能会使其更加困难......再次考虑CASE声明。

要使该复合开始/结束有意义,我们必须使“case”成为独立语句,而不是case / end对的一部分,因此所有这些都应该是有效的语法:

  case VALUE of
    1: DoSomething;
    2: DoSomethingElse;


  case VALUE of
    1: DoSomething;
    2: DoSomethingElse;
  else
    DoOther;


  case VALUE of
    1: DoSomething;
    2: begin
         DoSomethingElse;
         DoMore;
       end;
  else
    DoOther;


  case VALUE of
    1: DoSomething;
    2: begin
         DoSomethingElse;
         DoMore;
       end;
  else
  begin
    DoOther;
    DoMoreOther;
  end;


  case VALUE of
    1: DoSomething;
    2: begin
         DoSomethingElse;
         DoMore;
       end;

你可能不同意,但在我看来,突然这种更一致的语法实际上导致实际代码中的LESS一致性,即使代码编写符合的规则有更大的一致性。

答案 3 :(得分:3)

可能。但语言设计,尤其是具有一定历史的语言,很少是直截了当或理想的。

您可以在其他语言中看到类似的内容。例如,Java try之后需要一个块,并且不允许单个语句,尽管如果只查看其他控制结构,单个语句也可能有效。

为什么C和派生语言中的switch是一个块而个别情况不是?

答案 4 :(得分:2)

它与解析器的工作方式有关。开始/结束,尝试/除外和重复/直到所有包含语句块。对于开始块(伪代码),解析器的代码看起来像这样:

procedure ReadBlock;
begin
  Match('begin');
  while CurrentToken <> 'end' do
    ReadStatement;
  Match('end');
end;

这适用于那种类型的块。但是当您需要块结束行中的其他信息时(repeat / until的条件,以及try的异常处理块),那么您不希望它在结束之前运行,语言的语法预计在它之后没有任何东西。您可以修改语法,但这会给解析器增加很多复杂性。因此,您只需选择一个不同的关键字。

答案 5 :(得分:1)

我猜你问的是错误的问题。我的意思是,你可能没有看到if / while / for组和repeat / try组之间的区别。

第一组需要一些东西(条件或参数)才能开始。相反,第二个意味着BEGIN的东西。只需阅读单词:repeat(以下)并尝试(以下)。

Pascal干净,简洁,优雅,因为它专为普通人类读者而设计,Wirth教授在设计时会考虑学习编程。

答案 6 :(得分:1)

部分正确 - 在repeat <stmts> until <expr>声明中。

感觉有点作弊,你不需要BEGIN-END来表示复合语句的一致性,但这是为了避免不必要的痛苦。由于您在所有其他情况下都会看到,因此您需要使用开始包围效果来显示thenelse或循环do适用的代码部分的位置。 REPEAT-UNTIL是我能想到的唯一一个Pascal语句,它需要一个远远不够的第二部分 - 因为循环退出的条件在文本上是有意义的,它将被检查 - 循环体之后。另一种形式可能是

UNTIL <condition> DO <statement>

UNTIL <condition> DO
  BEGIN
    <statements>
  END

但是,解释并说服语言用户在块执行至少一次之后仅检查条件将会太令人困惑。所以Wirth不这样做是件好事。

关于try <stmts> except <stmts> end - 这不是来自原始的Pascal语言设计和规范,这已经被一些实现者(Borland?FreePascal?)认为是如此,所以难怪它是不一致的 - 与整体规格设计相比,我的想法更多的是“我能否在不破坏现有程序的情况下完成”。上面的答案给出了另一个语言扩展的例子 - else开关中的默认条款case - 虽然我发现这非常有用并且在Turbo Pascal的日子里使用过它 - 这是非常可怕的与else构造中if的使用不一致。因此,我发现我已经看到并使用了更好的另一个实现 - otherwise:后面跟着每个<value>:案例中的单个语句。