7

大多数 Pascal 控制结构对我来说都很有意义,例如:

for ... do {statement};

if (condition) then {statement};

while (condition) do {statement};

其中 {statement} 是单个语句或begin ... end块。我有一个问题:

repeat {statement-list} until (expression);

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

repeattry具有相同的一般结构,只接受单个语句或begin ... end块,而不是有一个没有被beginend正式阻止的语句列表,这不是更好吗?

4

7 回答 7

9

需要开始/结束的形式都存在于一行中——编译器没有其他方法可以知道块的结束位置。不需要开始/结束的表单有一个关闭结构,告诉编译器它在哪里结束,因此开始/结束只是多余的。不过,如果您愿意,您可以在这种情况下随意使用它。

于 2011-01-07T00:48:48.973 回答
8

Niklaus Wirth(Pascal 的设计者)在他的下一个语言Modula-2中纠正了这些不一致之处。在 Modula-2 中,复合语句如IFhave noBEGIN和 required END

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

其他控制结构,例如WHILEREPEAT.

于 2011-01-07T00:05:29.740 回答
5

问题是:不是更好吗?

答案是:这取决于,因为这类事情完全是主观的。除非你是或者像机器一样思考。

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

考虑 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(人类可读性和理解力的主观神)。

尽管在许多情况下它可能看起来并非如此,但我们人类实际上并不是机器。我们不需要将规则简化和减少到最小的一致集以使解析文本和理解它成为可能。我们需要一些规则,但我们可以处理更多,因为我们相对于机器的最大优势是思想自由,可以将我们从严格的句法和结构体系中解放出来,尤其是在这种句法和结构与冗余无关的情况下。

在这种情况下。

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

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

事实上,这些“更容易”更“一致”的规则,实际上可能会让一切变得更难……再考虑一下 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;

您可能不同意,但在我看来,突然之间这种更一致的语法实际上导致实际代码中的一致性降低,即使编写代码所遵循的规则具有更高的一致性。

于 2011-01-07T00:49:47.197 回答
3

大概。但是语言设计,尤其是有一点历史的语言,很少是直截了当或理想的。

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

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

于 2011-01-07T00:03:23.170 回答
2

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

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

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

于 2011-01-07T01:14:15.510 回答
1

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

第一组需要一些东西(条件或参数)来开始一些东西。相反,第二个暗示开始某事。只需阅读单词:重复(以下)并尝试(以下)。

Pascal 干净、简单、优雅,因为它是为普通人类读者设计的,Wirth 教授在设计它时考虑到人们正在学习编程。

于 2011-01-07T01:00:28.273 回答
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?)事后考虑的结果,所以难怪它是不一致的 - 这个想法更多的是“我可以在不破坏现有程序的情况下做到这一点”而不是整体规范设计。在上面的答案中给出了另一个语言扩展的例子——switch 中的默认子句else——case虽然我发现这非常有用并且在 Turbo Pascal 的日子里已经使用过它——这与结构中的使用非常else不一致if。因此,我找到了另一种我见过并使用得更好的实现——otherwise:在每种情况下都跟着一条语句<value>:

于 2011-02-04T00:24:46.910 回答