Why Pascal is Not My

 Favorite Programming Language


为什么Pascal不是我最喜欢的程序设计语言 

(后有一反面意见及本文原文)

Brian W. Kernighan, April 2, 1981

AT&T Bell Laboratories,  Murray Hill, New Jersey 07974

翻译:ljhhh0123@yahoo.com.cn


为了学习计算机英语,我根据google的自动翻译,再加润色,本文并未完成,但我会随时更新,如有更好的翻译,请发给我。谢谢。

摘要
Pascal程序设计语言已成为计算机科学的教育教学的主要语言。它还强有力的影响了其后语言的开发,特别是后来的Ada语言。

Pascal最初的主要目的是作为教学语言,但它已被越来越多的被建议用来进行正式(严肃)的程序设计。而且也包括系统程序设计任务,甚至是操作系统的编写。

Pascal,至少在它的标准形式,简单的说来,不适合进行严肃的程序设计。本文讨论了我个人的一些原因。

1. 起源

本文起源于两个事件:有大量的论文来比较C语言和Pascal(1,2,3,4)语言,和我个人决定用Pascal重写《软件工具》(5)一书。

比较C和Pascal是有点像比较Learjet(喷气式飞机)和Piper Cub(微型活塞式飞机),一个是获取工作,而另一种是学习如何工作。所以这种比较往往是有点牵强。但是,《软件工具》一书的修正版本会有更多相关的比较。那里的程序起始是用Ratfor语言编写,一个“结构化的”Fortran方言的预处理器实现。由于Ratfor是伪装的Fortran,它有一些Pascal的东西:数据类型更适合于字符处理,数据结构能力更强,和强类型用来强制数据的真实可靠。

结果是,用Pascal重写程序,比我预期的更难。本文就是试图提取有关Pascal的编程适宜性(不同于编程学习)的一些的经验教训。这不是拿C或Ratfor与Pascal进行的比较。

程序最早的应用是用pascal方言用来解释圆周率,由加州大学伯克得分校提供。语言接近Jensen和Wirth名义上的标准(6),具有良好的诊断和细心的运行时检查。此后,程序已经可以运行,除了新的基本函数库不用改变,还在其他四个系统:一阿姆斯特丹自由大学(以下简称VU为自由大学)的解释器,一个伯克利系统的VAX版本(一个真正的编译器),一个Whitesmiths责任公司供应编译器,和加州大学圣地亚哥分校在Z80上的Pascal。但所有这些Pascal系统最后都用C编写。

Pascal是讨论得最多的语言。最近书目(7)列出了175项讨论、分析和辩论的标题。最经常引用的论文(值得一读)是Habermann的强烈批判(8)和Lecarme和Desjardins同样强烈的反驳(9)。Boom和DeJong的文章(10)也是良好的读物。Wirth自己对Pascal的评价在[11]。我没有想要或能力来概括这些文字;本文代表我个人的意见和大部分重复别人提出的意见。我试着组织围绕问题的其他材料

    ·类型和作用域
    ·控制流
    ·环境
    ·修饰
    
并在每个方面或多或少减少顺序的重要性。

我先表示我的结论:Pascal可能是一种令人钦佩教初学者如何编程的语言;我没有第一手经验。这是1968年的一个相当大的成就。这无疑影响了最近的语言的设计,其中Ada很可能是最重要的设计。但在它的标准形式(包括现有的和计划的),Pascal不能足够的胜任编写真正的程序。它仅适用于小型的,独立的程序,并且与环境交互能力差。这使人写出的软件都没有多大用。

2. 类型和作用域
Pascal(差不多)是强类型语言。粗略地说,这意味着每一个程序对象具有良好定义的类型,它隐式的定义了操作对象的合法值。语言的保证,它会禁止一些非法值和操作,通过编译和运行时检查。当然,编译器可能不会完成所有的语言定义的隐含检查。此外,强类型不会与量纲分析相混淆。如果一个定义类型的'apple'和'orange'

    type
        apple = integer;
        orange = integer;

然后涉及apple和oranger的任意数学表达式,都是完全合法的。

强类型有不同的方式。例如,函数和过程的参数的类型匹配检查。在过去,Fortran自由的传递浮点参数到子程序会被认为是一个整数。我认为Pascal的这个特性是令人满意的,因为这样构造的话肯定会导致错误警告。

整型变量可以被声明为有一个范围的合法值,编译器和运行时支持确保一个大的整型变量不能放进一个小的整型变量,这也似乎是一种服务,虽然运行时检查是一种强制的处罚。

让我们继续前进的类型和作用域的一些问题。

2.1  数组的大小是其类型的一部分

如果一个声明

     var     arr10 : array [1..10] of integer;
             arr20 : array [1..20] of integer;


然后arr10和arr20分别是10和20个整数的数组。假设我们要编写一个过程'sort'来排序一个整数数组。由于arr10和arr20有不同的类型,它是不可能编写一个简单的过程来将它们排序。

这些地方会特别影响软件工具,我想一般的程序是,可以创建一个程序库,它可以真正的做一些一般的事和通用流行的操作,比如排序。

在特定的数据类型最常见的影响是 'array of char',在Pascal的字符串是一个字符数组。考虑编写一个函数'index(s,c)',将返回字符c在字符串s第一次出现的位置,如果它不存在就返回0。问题是如何处理'index'的字符串参数。调用"index('hello',c)"和调用"index('goodbye',c)"不能同时是合法的,因为字符串有不同的长度。 (我忽略的是如何检测像'hello'常量字符串结尾的问题,因为它不能。)接下来的尝试是

    var     temp : array [1..10] of char;
            temp := 'hello';

            n := index(temp,c);


但对赋值给'temp'非法的,因为'hello'和'temp'的长度不同。

从这个无限的倒退中逃脱的唯一方法就是要为每个可能的字符串的大小定义一个成员函数,或者使所有字符串具有相同长度的(包括常量字符串'define')。

后一种方法是两大害中较轻的。在'Tools'中,'string'类型被声明为

     type    string = array [1..MAXSTR] of char;


其中常数“MAXSTR”是"足够大",所有程序的所有字符串,都恰好正是这种大小。这是很不理想,虽然它使人们有可能获得程序的运行。它不解决创造真正有用的例程库的问题。

在一些情况下,根本不能接受的使用固定大小的数组表示。例如,使用'Tools'程排序文本行就要用一些文本行来填充内存,它的运行时间在很大程度上取决于如何充分的填充内存。

因此,对于'sort',另一种是用来表示一个字符数组和一个到这个数组索引:

     type    charbuf = array [1..MAXBUF] of char;
             charindex = array [1..MAXINDEX] of 0..MAXBUF;


但是,过程和函数处理固定长度的形式不能使用可变长度的形式,一个完整的程序集需要复制和比较这种表示的字符串。这在Fortran或C中,一个函数就够了。

如上所述,一个常量字符串写成

     'this is a string'

并有型'packed array [1..n] of char',其中n是长度。因此,不同长度的字符串具有不同的类型。唯一的方法是,把输出的消息都处理成一样的最大长度。

     error('short message                    ');
     error('this is a somewhat longer message');


许多商业Pascal编译器提供一个'string'的数据类型,来明确避免这个问题;'string'被视为同一类型而无论大小。这解决了这一单个数据类型的问题,仅此而已。但它也未能解决第二个问题,比如计算一个常量字符串的长度,另外,内置的功能是通常的解决方案。

Pascal爱好者经常声称,为应对数组大小的一个问题不过是复制一些库程序和填写参数的程序在手。但这种抵御的声音大都是微弱的:(12)

``由于数组的边界是类型(或更确切地说是它的索引类型)的一部分,它不可能定义一个过程或函数应用于数组的不同边界上。虽然这种限制可能会成为一个严重的问题,我们使用Pascal的经验表明,它发生的非常频繁。[...]然而,需要绑定的参数数组的大小是使用有关的程序库严重缺陷。''
这种笨拙是Pascal最大的一个问题。我相信,如果它能被修复,语言的应用将会扩大一个数量级。建议的ISO标准为Pascal(13)提供这样一种修复(``符合性数组模式''),但接受这个作为标准的一部分显然仍存在疑问。

2.2  没有静态变量和初始化

一个'static'变量(在使用Algol的地方通常被称为一个'own'变量)对一些程序是私有的,并保留其值从一个程序调用到下一个调用。事实上,Fortran的变量是内部静态的,除了COMMON;在C语言里“static”声明,可以应用到局部变量。 (严格地说在Fortran 77,必须使用SAVE强制静态属性。)

Pascal没有这样的存储类。这意味着,如果一个Pascal函数或过程打算从一个调用到另一个调用之间记住一个值时,必须使用具有外部变量的函数或过程。因此,对于其他程序它必须是可见的,其名称必须在更大的范围内是唯一的。这种问题的一个简单的例子是一个随机数发生器:用于计算输出值必须保存到计算下一个,所以它必须是一个变量,其生存期包含了随机数生成所有调用存储。实际上,这通常是最外层的程序块。因此,这样的变量声明是远离它实际使用的地方。

一个例子来自于《工具(Tools)》一书第7章所描述的文本格式化。变量 'dir' 控制从行调整插入多余的空白行,获得左,右交替插入的方向。在Pascal中,代码如下:

     program formatter (...);

     var
             dir : 0..1;     { direction to add extra spaces }
             .
             .
             .
     procedure justify (...);
     begin
             dir := 1 - dir; { opposite direction from last time }
             ...
     end;
             ...

     begin { main routine of formatter }
             dir := 0;
             ...
     end;

变量'dir'的声明、初始化和使用分散在各处,相距数百行。在C或Fortran里,'dir'可在程序需要时做成私用的:
              ...
     main()
     {
             ...
     }
             ...

     justify()
     {
             static int dir = 0;

             dir = 1 - dir;
             ...
     }

当然,还有一个更大的规模上相同的问题很多其他的例子,对函数缓冲I/O,存储管理和符号表中的所有映入脑海。
至少有两个相关的问题。Pascal没有提供方法来初始化静态变量(即在编译时),也没有什么类似于Fortran的DATA语句或类似的初始化:

     int dir = 0;

在C语言里,这意味着,一个Pascal程序必须包含明确的赋值语句来初始化变量,如:

     dir := 0;

这使得程序的源代码文本更大,而且在运行时体积也更大。

此外,缺乏初始化加剧了大范围的问题,这都归因于缺乏静态存储类。初始化的时机是在开始的时候,所以无论是主程序本身带有大量的初始化代码,或者调用一个或多个程序做初始化。在这两种情况下,要初始化的变量必须是可见的,这实际上意味着在层次结构的最高水平。其结果是,任何变量,必须在全局范围进行初始化。

第三个困难是,没有两个例程来共享一个变量的方式,除非它是至少达到或超过他们的共同祖先声明。 FORTRAN COMMON和C的外部静态存储类都提供了两个例程私下合作的方式,没有分享他们的祖先的信息。

新标准不提供静态变量,初始化或无层级的通讯。

2.3 相关程序的组件必须分开

由于原始的Pascal是用一单遍编译器实现的,语言坚信在使用前先声明。特别是,过程和函数必须先声明(函数体和所有),然后再使用它们。其结果是,一个典型的Pascal程序从下往上读 - 所有的程序和功能显示在代码的各级调用之前。其中的功能设计和使用的顺序基本上是相反的。
C和Ratfor的设施#include在一定程度上可以缓解:源文件可以在需要时导入进来,而不使程序杂乱。 #include不是标准Pascal的一部分,虽然UCB,VU和Whitesmiths编译器都提供了。

还有一种'forward'的声明,允许在Pascal分离的功能还是从机构的议事头声明,它是定义相互递归程序之意。当身体被声明以后,关于该声明头可能只包含函数的名称,不得重复从第一个实例的信息。

一个相关的问题是,Pascal有着严格的顺序,它愿意接受声明。每个过程或函数包括

label label declarations, if any
const constant declarations, if any
type type declarations, if any
var variable declarations, if any

procedure and function declarations, if any
begin
body of function or procedure
end


这意味着为了编译器的方便,类型的所有声明必须组合在一起的,即使程序员想保持在一起的逻辑相关,以便了解程序更好的东西。由于方案将提交给编译器一次全部,它几乎是不可能保持的声明,初始化和变量的类型和并拢的使用。即使是最敬业的Pascal的一些支持者同意:(14)
``由于无法使这些组件构建大型程序,这是Pascal的最令人沮丧的限制之一。'
一个文件包含工具帮助这里只有一点点。
新标准不放松对声明的顺序的要求。

2.4  不能分开编译(There is no separate compilation)

官方的Pascal语言不提供单独的编译,要做什么取决于实现。有些(例如伯克利的实现)完全禁止它,这是最接近语言的精神和字面意义上完全匹配的。许多人提供了一个声明,表示指定一个函数体外部定义。在任何情况下,所有这些机制不规范,不同的系统又不同。
从理论上讲,没有单独编译的需要 - 如果一个编译器是非常快的(如果所有程序源总是可用的,如果一个人的编译器有一个文件包含工具,而不需要源的多个副本),则重新编译一切是等价的。在实践中,当然,编译器永远不会足够快,而源通常是隐藏的,文件包含是不是语言的一部分,所以这种变化是费时的。

有些系统允许单独编制,但不验证跨边界类型的一致性。这将创建一个强类型的巨洞。 (大多数其他语言做无交叉编译检查要么??,所以Pascal没有这方面的劣势。)我已经看到至少有一个文件(大发慈悲未公布)上页严惩未能在单独的编译边界检查类型C同时建议第N +1的办法,以应付Pascal是编译程序分开,以避免类型检查。

新标准不提供单独编译。

2.5  类型和作用域的一些杂项问题(Some miscellaneous problems of type and scope)

以下几点大多是轻微的刺激,但我在某个地方坚持这几点。
这是不合法的名称,过程的文字名形参不是基本类型,下面是不允许的:

     procedure add10 (var a : array [1..10] of integer);


相反,我们必须发明一种类型的名称,做一个类型声明,并宣布正式参数是一个该类型的实例:

     type    a10 = array [1..10] of integer;
     ...
     procedure add10 (var a : a10);


当然,如果是类型声明是从过程上物理分离的。该发明的类型名称是对于那些经常使用的类型是有帮助的,但它是一个只使用一次的麻烦。
我很高兴可以声明“var”作为函数或过程的形参;过程中明确指出,它打算修改参数。但调用程序没有办法声明一个修改的变量 - 信息只在一个地方,而两地会更好。 (半个面包总比没有好,虽然 - Fortran告诉用户不需要变量。)

这也是一个小麻烦,数组是按值传递的默认-净效果是,每个数组参数声明“VAR”所没有的思维程序员或多或少。如果“VAR”申报不小心忽略,由此产生的错误是潜移默化的。

Pascal的“set”构造似乎是一个好主意,概念上的便利,并提供一些免费的类型检查。例如,一组测试,如

    if (c = blank) or (c = tab) or (c = newline) then ...

可写,而更清楚,也许更有效地为

     if c in [blank, tab, newline] then ...

但在实践中,集合类型是没有用的远不止这些,因为一个集大小强烈依赖于实现(可能是因为它是在原来的疾病预防控制中心的执行情况,59位)。例如,它很自然地尝试写功能“isalphanum(三)”(``是c字母?'')作为

     { isalphanum(c) -- true if c is letter or digit }
     function isalphanum (c : char) : boolean;
     begin
             isalphanum := c in ['a'..'z', 'A'..'Z', '0'..'9']
     end;

但在许多实现Pascal(包括原)这段代码会失败,因为集只是太小了。因此,一般最好设置闲置如果打算编写可移植程序。 (这个具体的例行还运行了一个数量级的集速度比射程试验或数组的引用。)

2.6  没有逃脱

在必要时没有覆盖类型的机制,没有类似C语言的"cast(转型)"机制,这意味着它是不可能用Pascal写出这样的存储分配器或I/O系统的方法,因为没有这样谈论的对象的类型,他们的回报,也没有办法强迫到另一个使用任意类型的对象等。 (严格地说,是有近似变量记录的类型检查是个大漏洞,使得一些其他形式的非法类型可以匹配。)

3. 控制流

Pascal控制流的缺陷是次要的,但很多 - 无数个死亡点,而不是单一的朝向至关重要的地方。
不存在的逻辑运算符“and”与“or”来保证求值的顺序 -不像在C里的&&和无||,它会与大多数其他语言共享,伤害通常在于闭环控制:

     while (i <= XMAX) and (x[i] > 0) do ...

使用Pascal是极不明智的,因为没有办法保证,i是在X[i]之前测试的。

顺便说一下,在这个代码中的括号是强制性的语言已与底部有关联的只有四个运算符优先级的水平。

退出循环没有“break”为语句。这与结构化编程的支持者所信奉的一个入口,一个出口的理念一致,但它确实导致累赘或重复的代码,特别是在与无法控制的,其中的逻辑表达式的计算顺序耦合。考虑这种常见的情况,在C或Ratfor表示:

     while (getnext(...)) {
             if (something)
                     break
             rest of loop
     }

由于没有“break”语句,使用Pascal的第一次尝试是

     done := false;
     while (not done) and (getnext(...)) do
             if something then
                     done := true
             else begin
                     rest of loop
             end

但是这样并不能工作,因为没有办法迫使“not done”是前“getnext”下次调用评估。这导致,经过多次错误的开始,到

     done := false;
     while not done do begin
             done := getnext(...);
             if something then
                     done := true
             else if not done then begin
                     rest of loop
             end
     end

当然惯犯可使用“goto”和一个标签(数字仅它必须声明)退出循环。否则,提前退出是一个痛苦,几乎总是需要一个布尔变量的发明和一定量的狡猾。比较发现在一个Ratfor数组的最后一个非空白:

     for (i = max; i > 0; i = i - 1)
             if (arr(i) != ' ')
                     break

使用Pascal:

     done := false;
     i := max;
     while (i > 0) and (not done) do
             if arr[i] = ' ' then
                     i := i - 1
             else
                     done := true;

一个'for'循环指数为外循环定义,所以它不可能找出一个人是否到了最终还是没有。一个'for'循环增量只能是+1或-1,未成年人的限制。
有没有“回报”的说法一出原因再于一身。函数返回值通过设置一个伪变量(如FORTRAN)值,然后脱落函数结束。这有时会导致扭曲,以确保所有路径实际得到的与正确的价值函数结束。也没有标准的方法来终止除非到达最外层块结束的执行,虽然许多实现提供了一个“停止”,导致立即终止。

在“案例”的说法是更好的设计比C,除了没有“default”条款和行为是不确定的,如果输入的表达式不匹配任何个案。这一重要遗漏呈现“案例”构造几乎一文不值。在超过6000行Pascal在“Software Tools in Pascal(Pascal软件工具)”,我用它只有四次,但如果出现了一个“default”,一个“case”将服务至少在十几个地方。

新标准的机制对这些问题没有任何的帮助。

4. 环境

在Pascal运行时环境相对稀少,而且没有扩展机制,也许除了“官方”语言的源码库机制。

Pascal的内置I/O有一个当之无愧的坏名声。它坚信面向记录的输入和输出。它也有一个超前约定交互环境中是很难实现的。基本上,问题是,I/O系统认为,它必须读取正在处理的记录一个记录之前。在一个互动系统,这意味着,当一个程序启动时,它的第一个操作就是尽量阅读前,本身已执行程序的任何为输入的第一线终端。但在计划

     write('Please enter your name: ');
     read(name);
     ...

预读导致程序挂起,等待输入打印前的提示,它要求。
它可以逃脱这个I/O设计的恶果最受非常认真执行,但不是所有的Pascal系统,这样做,而且在任何情况下,它是相对昂贵。

在I/O设计体现了原有的操作系??统赖以Pascal的设计,甚至沃斯承认偏见,虽然不是它的缺陷(15)假设该文本文件的记录组成,也就是说,文本行。当一行的最后一个字符被读取后,内置的功能“eoln”变为真;在这一点上,我们必须称之为“readln来启动一个新的阅读线和复位??”eoln“。同样,当最后一个字符的文件被读取时,内置的“EOF”变为真。在这两种情况下,“eoln”和“EOF”必须进行测试之前每个“读”,而不是之后。

鉴于此,相当大的痛苦,必须采取合理的模拟输入。这样的“GETC”工程大学伯克利分校和VU I/O系统,但实施可能并不一定为别的:

     { getc -- read character from standard input }
     function getc (var c : character) : character;
     var
             ch : char;
     begin
             if eof then
                     c := ENDFILE
             else if eoln then begin
                     readln;
                     c := NEWLINE
             end

             else begin
                     read(ch);
                     c := ord(ch)
             end;
             getc := c
     end;

类型“字”是不一样的“字符”一样,因为ENDFILE也许NEWLINE不是一个“字符”变量的合法值。
目前并没有获得除命名(有效)的逻辑中的“程序”声明,每个程序单元号开始预定义文件到文件系统中的所有概念。这显然??反映了疾病预防控制中心批制度,最初是Pascal。文件变量

     var fv : file of type

是一种非常特殊的对象 - 它不能被分配??到,也只有通过使用内置的像“EOF”,“eoln”,“读”,“写”,“复位”和“重写”过程的调用。 (“重设”倒回一个文件,使它成为重读准备;'重写'使文件编写做好准备。)
Pascal的大多数实现提供了一个逃生舱口就允许名称文件从外部环境,而不是方便,而不是standardly。例如,许多系统调用允许在文件名参数“复位”和“重写”:

     reset(fv, filename);

但是,“复位”和“改写”是过程,不是函数 - 有没有地位,没有办法返回重新获得控制,如果由于某种原因,试图访问失败。 (UCSD提供了编译时间标志,禁用正常中止。)而且,由于FV的不能在表达式中出现像
     
     reset(fv, filename);
     if fv = failure then ...

有没有朝这个方向逃跑或者。这基本上是不可能的束缚使得编写程序,从错误中恢复的文件名拼写,等我从来没有解决的“工具”修订它充分。
没有获得命令行参数,可能再次反映Pascal的批处理起源的概念。本地程序可以允许添加非的标准程序的环境中。

既然是不可能写在Pascal一般用途的存储分配器(那里是没有办法谈的类型,这样的函数将返回),语言有一个从一个内置的所谓“新”的过程,分配空间堆。只有定义类型可以分配,所以它是不可能的分配,例如,任意大小的数组来保存字符串。由“新”返回的指针可能被传递而不是操纵:没有指针运算。有没有办法重新获得控制权,如果储存耗尽。

新标准提供了在这些领域没有任何变化。

5. 修饰问题

这些问题大多是有经验的程序员厌烦,一些可能还会滋扰初学者。它们都可以连在一起。
Pascal,与大多数其他以Algol为灵感的语言一样,使用分号而不是结束(在PL/I和C)作为语句分隔。因此必须有一个什么样的声明是把复杂的概念,合理妥善分号。也许更重要的是,如果一个人大约在适当的地方使用它们严重,相当数量的滋扰编辑需要。考虑第一个程序片段:

     if a then
             b;
     c;

但如果事情必须在b之前插入,它不再需要一个分号,因为它现在前面一个“结束”:

     if a then begin
             b0;
             b
     end;
     c;

现在,如果我们添加一个'else',就必须消除对'end'的分号:

     if a then begin
             b0;
             b
     end
     else
             d;
     c;

以及等等等等用分号上下翻飞的方案来进行下去。

一个普遍接受的程序员心理学实验的结果是,分号作为分隔约10倍更容易比分号作为结束符错误(16)(在Ada,(17)最重要的语言基础上Pascal,分号结束符。)幸运的是,Pascal可以几乎总是闭一只眼,并逃脱分号作为结束符。例外的是在像声明,其中与终端分离问题似乎并不严重反正地方,就在“其他”,这是很容易记住。

C和Ratfor程序员发现'begin'和'end'笨重相比,{和}。

一个函数名本身是该函数调用,而没有办法区分从一个简单的变量除非知道该函数的名称,如函数调用。Pascal采用了具有像在函数变量函数的名称的行为Fortran的把戏,但如在Fortran函数的名字真的是一个变量,并可以出现在表达式中,在Pascal,其表达式的外观是一个递归调用:如果f是一个零参数的函数,'F:= F +1为F的递归调用

有一个经营者缺乏(可能涉及到优先级的缺乏)。特别是,有没有位操作运算符(AND,OR,XOR等)。我只是放弃了试图写下面的Pascal中琐碎的加密程序:

     i := 1;
     while getc(c) <> ENDFILE do begin
             putc(xor(c, key[i]));
             i := i mod keylen + 1
     end

因为我不能写一个合理的“异或”的功能。设置的类型有点帮助这里(这么说),但还不够,声称Pascal是一个系统编程语言的人一般都忽略了这一点。例如,[18,第685]``Pascal是目前[1977]系统编程和软件实现最好的语言,似乎有点天真。
有没有空字符串,也许是因为Pascal使用翻了一番引用符号来表示字符串中嵌入一个报价:

     'This is a '' character'

有没有办法投入字符串非图形符号。事实上,非图形字符在unpersons感更强,因为它们不属于任何标准语言的一部分提及。如换行符,制表符等概念的处理系统在每一个“专案”的方式,通常是通过了解有关字符集(如ASCII换行符的十进制值10)的东西。

There is no macro processor.  The 'const' mechanism for defining manifest constants takes care of about 95 percent of the uses of simple #define statements in C, but more involved ones are hopeless.  It is certainly possible to put a macro preprocessor on a Pascal compiler.  This allowed me to simulate a sensible 'error' procedure as

     #define error(s) begin writeln(s); halt end

('halt' in turn might be defined as a branch to the end of the outermost block.) Then calls like

     error('little string');
     error('much bigger string');

work since 'writeln' (as part of the standard Pascal environment) can handle strings of any size.  It is unfortunate that there is no way to make this convenience available to routines in general.
The language prohibits expressions in declarations, so it is not possible to write things like

      const   SIZE = 10;
      type    arr = array [1..SIZE+1] of integer;

或者简单的就像

      const   SIZE = 10;
              SIZE1 = SIZE + 1;

6. 观点

在努力重写《软件工具》一书的程序从1980年3月开始,间歇的持续到1981年1月。最终此书(19)在1981年6月发布。那段时间我逐渐适应了与Pascal(修饰,控制流不足)表面的问题,并并发着不完善的解决方案(数组的大小,运行时环境)来使它好用。

要完成书里的程序,还要有良好的设计,是个不平凡的任务。但他们没有被有效的,也不是非常复杂的操作系统及其相互作用,使我能够得到一些漂亮的杂牌解决方案,那些根本就没有真正的解决方案。

没有明显的地方显示出Pascal优于C,但也有它是一个多Ratfor明显改善的几个地方。迄今为止最明显的就是递归:几个节目更清洁的书面递归时,特别是模式搜索,快速排序,评价和表达。

枚举数据类型是一个好主意。同时,他们划定的合法值的范围和文档中。记录有助于组相关的变量。我发现使用相对较少的指针。

布尔变量是整数比布尔条件更好;原Ratfor方案中有些不自然,因为Fortran的建设的逻辑变量的设计不当。

偶尔Pascal的类型检查会警告的手滑书面方案;价值观的运行时检查还表示不时的错误,特别是下标范围的行为。

至于消极的一面,重新编译一个从无到有的大型计划,以改变源一行是非常烦人;独立编译或没有类型检查,是对大型程序的强制性。

我来自一个事实,字符被部分Pascal和Fortran的部分不小的好处,因为字符串和非图形Pascal治疗等不足。在这两种语言,这是令人吃惊笨拙初始化的关键字,错误信息,如表和文字字符串。

完成的项目是在对他们的Ratfor等同的源代码行数相同的一般。起初这让我很吃惊,因为我的偏见是,Pascal是一个冗长,少表达语言。真正的原因似乎是在像Pascal许可证限制并在Fortran的循环(即,便携式的Fortran 66)没有,所以一些无用的分配可以消除标地任意表达式;此外,Ratfor程序申报功能,而Pascal的做没有。

临结束,让我总结一下反对Pascal的要点。

1.由于数组的大小是其类型的一部分​​,它是不可能写出通用例程,也就是要处理不同大小的阵列。特别是,字符串处理是非常困难的。
变量需要更多的范围比他们应该 -

2.在静态变量的初始化和通信方式的非层次相结合,破坏当地的`` ''程序缺乏。
各申报散射程序组件,逻辑上属于一起执行分开,将语言的力量的过程和函数是在一个不自然顺序排列一通的性质。

3.单独编制的缺乏阻碍了大型项目的发展,而不能使用的库。
逻辑表达式的计算顺序不能得到控制,从而导致复杂的代码和随机变量。

6.在“案例”的说法是被阉割的,因为没有违约条款。

7.标准I/O是有缺陷的。没有与文件或程序参数作为标准语言的一部分,并没有合理的处理提供扩展机制。

8.语言缺乏用于装配大型程序所需的工具最多,最显着的文件包含。

9.没有逃脱。

最后这一点也许是最重要的。语言是不足,但界限清楚,因为没有办法逃脱它的局限性。有没有转换禁用类型检查时必需的。有没有办法更换明智的做法有缺陷的运行时环境,除非控制编译器定义了``标准程序。''的语言是封闭的。
人们谁使用严重的编程陷入致命的陷阱Pascal。

因为语言是如此的无能,它必须扩展。但各组扩展了自己的方向Pascal,使它看起来像任何一种语言,他们真正想要的。单独编译,Fortran语言类常见,字符串数据类型,内部静态变量的初始化,八进制数,位域等扩展,都增加了语言的工具为一组,而破坏其移植性性。

我觉得做超出Pascal原定目标的事是一种错误。在它的形式看来,Pascal是一个玩具语言,适合教学,但不适合真正的编程。

致谢

I am grateful to Al Aho, Al Feuer, Narain Gehani, Bob Martin, Doug McIlroy, Rob Pike, Dennis Ritchie, Chris Van Wyk and Charles Wetherell for helpful criticisms of earlier versions of this paper.

[1] Feuer, A. R. and N. H. Gehani, ``A Comparison of the Programming Languages C and Pascal - Part I: Language Concepts,'' Bell Labs internal memorandum (September 1979).

[2] N. H. Gehani and A. R. Feuer, ``A Comparison of the Programming Languages C and Pascal - Part II: Program Properties and Programming Domains,'' Bell Labs internal memorandum (February 1980).

[3] P. Mateti, ``Pascal versus C: A Subjective Comparison,'' Language Design and Programming Methodology Symposium, Springer-Verlag, Sydney, Australia (September 1979).

[4] A. Springer, ``A Comparison of Language C and Pascal,'' IBM Technical Report G320-2128, Cambridge Scientific Center (August 1979).

[5] B. W. Kernighan and P. J. Plauger, Software Tools, Addison-Wesley, Reading, Mass. (1976).

[6] K. Jensen, Pascal User Manual and Report, Springer-Verlag (1978). (2nd edition.)

[7] David V. Moffat, ``A Categorized Pascal Bibliography,'' SIGPLAN Notices 15(10), pp. 63-75 (October 1980).

[8] A. N. Habermann, ``Critical Comments on the Programming Language Pascal,'' Acta Informatica 3, pp. 47-57 (1973).

[9] O. Lecarme and P. Desjardins, ``More Comments on the Programming Language Pascal,'' Acta Informatica 4, pp. 231-243 (1975).

[10] H. J. Boom and E. DeJong, ``A Critical Comparison of Several Programming Language Implementations,'' Software Practice and Experience 10(6), pp. 435-473 (June 1980).

[11] N. Wirth, ``An Assessment of the Programming Language Pascal,'' IEEE Transactions on Software Engineering SE-1(2), pp. 192-198 (June, 1975).

[12] O. Lecarme and P. Desjardins, ibid, p. 239.

[13] A. M. Addyman, ``A Draft Proposal for Pascal,'' SIGPLAN Notices 15(4), pp. 1-66 (April 1980).

[14] J. Welsh, W. J. Sneeringer, and C. A. R. Hoare, ``Ambiguities and Insecurities in Pascal,'' Software Practice and Experience 7, pp. 685-696 (1977).

[15] N. Wirth, ibid., p. 196.

[16] J. D. Gannon and J. J. Horning, ``Language Design for Programming Reliability,'' IEEE Trans. Software Engineering SE-1(2), pp. 179-191 (June 1975).

[17] J. D. Ichbiah, et al, ``Rationale for the Design of the Ada Programming Language,'' SIGPLAN Notices 14(6) (June 1979).

[18] J. Welsh, W. J. Sneeringer, and C. A. R. Hoare, ibid.

[19] B. W. Kernighan and P. J. Plauger, Software Tools in Pascal, Addison-Wesley (1981).


一个读者的反面意见

说句实话,pascal确比C方便、实用。一个从未接触过程序设计的人10天能学会pascal,但10天很难学会C!现在用C的人多是因为学校里只讲C,其实pascal有很多优于C的地方。举个最简单的例子:要输入a、b两个整数,

pascal写为 read(a,b); C语言写为 scanf("%d %d",&a,&b); 比较一下就知道差别了。 

pascal有布尔类型,C没有(C++Builder当然有了,是从pascal引进的),

pascal有集合类型,C没有;

pascal有变量参数的概念,C没有;

pascal可以在一个函数内部再定义函数,C不能;

pascal查错能力极强,C较弱;

pascal编译速度极快,C较慢;

pascal不分大小写,打字速度快,C远不及;

pascal能直接嵌入汇编,C不能;

pascal里表示域的所属关系用 . (点),C用->,不如pascal方便;

pascal里没有参数的函数不用加个括号,C得加一个空括号;

pascal可以把用到的很多单元写在一行(uses ...),C则是每个库都得写一行(#include ...),等等。

C语言里的各种数据结构和算法pascal均能实现,而且可以用一种更简便的办法实现。

要说具体点,那就多得说不完了。

看看pascal编译器和C编译器,那简直是天壤之别。

虽说pascal没有宏的概念,但有常量的概念。 
基本语法方面的差别在Delphi和C++Builder中仍然存在。

Delphi中的资源远比C++Builder多。

Delphi中的所有函数可以看到源代码,而在C++Builder中很多函数只能看到一个“//pascal unit”的注释。Delphi的查错能力远比C++Builder强,

Delphi的编译速度有C++Builder的10倍,(不信自己可以去试) 。

要是C比pascal更好用,那么Borland为什么要用pascal而不用C来编写VCL呢?


附录:Brian W. Kernighan,原文

Brian W. Kernighan, April 2, 1981AT&T Bell Laboratories, Murray Hill, New Jersey 07974

Abstract:

The programming language Pascal has become the dominant language of instruction in computer science education. It has also strongly influenced languages developed subsequently, in particular Ada.Pascal was originally intended primarily as a teaching language, but it has been more and more often recommended as a language for serious programming as well, for example, for system programming tasks and even operating systems.Pascal, at least in its standard form, is just plain not suitable for serious programming. This paper discusses my personal discovery of some of the reasons why.1. GenesisThis paper has its origins in two events - a spate of papers that compare C and Pascal(1, 2, 3, 4) and a personal attempt to rewrite 'Software Tools'(5) in Pascal.Comparing C and Pascal is rather like comparing a Learjet to a Piper Cub - one is meant for getting something done while the other is meant for learning - so such comparisons tend to be somewhat farfetched. But the revision of Software Tools seems a more relevant comparison. The programs therein were originally written in Ratfor, a ``structured'' dialect of Fortran implemented by a preprocessor. Since Ratfor is really Fortran in disguise, it has few of the assets that Pascal brings - data types more suited to character processing, data structuring capabilities for better defining the organization of one's data, and strong typing to enforce telling the truth about the data.It turned out to be harder than I had expected to rewrite the programs in Pascal. This paper is an attempt to distill out of the experience some lessons about Pascal's suitability for programming (as distinguished from learning about programming). It is not a comparison of Pascal with C or Ratfor.The programs were first written in that dialect of Pascal supported by the Pascal interpreter pi provided by the University of California at Berkeley. The language is close to the nominal standard of Jensen and Wirth,(6) with good diagnostics and careful run-time checking. Since then, the programs have also been run, unchanged except for new libraries of primitives, on four other systems: an interpreter from the Free University of Amsterdam (hereinafter referred to as VU, for Vrije Universiteit), a VAX version of the Berkeley system (a true compiler), a compiler purveyed by Whitesmiths, Ltd., and UCSD Pascal on a Z80. All but the last of these Pascal systems are written in C.Pascal is a much-discussed language. A recent bibliography(7) lists 175 items under the heading of ``discussion, analysis and debate.'' The most often cited papers (well worth reading) are a strong critique by Habermann(8) and an equally strong rejoinder by Lecarme and Desjardins.(9) The paper by Boom and DeJong(10) is also good reading. Wirth's own assessment of Pascal is found in [11]. I have no desire or ability to summarize the literature; this paper represents my personal observations and most of it necessarily duplicates points made by others. I have tried to organize the rest of the material around the issues oftypes and scopecontrol flowenvironmentcosmeticsand within each area more or less in decreasing order of significance.To state my conclusions at the outset: Pascal may be an admirable language for teaching beginners how to program; I have no first-hand experience with that. It was a considerable achievement for 1968. It has certainly influenced the design of recent languages, of which Ada is likely to be the most important. But in its standard form (both current and proposed), Pascal is not adequate for writing real programs. It is suitable only for small, self-contained programs that have only trivial interactions with their environment and that make no use of any software written by anyone else.2. Types and ScopesPascal is (almost) a strongly typed language. Roughly speaking, that means that each object in a program has a well-defined type which implicitly defines the legal values of and operations on the object. The language guarantees that it will prohibit illegal values and operations, by some mixture of compile- and run-time checking. Of course compilers may not actually do all the checking implied in the language definition. Furthermore, strong typing is not to be confused with dimensional analysis. If one defines types 'apple' and 'orange' with type apple = integer; orange = integer;then any arbitrary arithmetic expression involving apples and oranges is perfectly legal.Strong typing shows up in a variety of ways. For instance, arguments to functions and procedures are checked for proper type matching. Gone is the Fortran freedom to pass a floating point number into a subroutine that expects an integer; this I deem a desirable attribute of Pascal, since it warns of a construction that will certainly cause an error.Integer variables may be declared to have an associated range of legal values, and the compiler and run-time support ensure that one does not put large integers into variables that only hold small ones. This too seems like a service, although of course run-time checking does exact a penalty.Let us move on to some problems of type and scope.2.1. The size of an array is part of its typeIf one declares var arr10 : array [1..10] of integer; arr20 : array [1..20] of integer;then arr10 and arr20 are arrays of 10 and 20 integers respectively. Suppose we want to write a procedure 'sort' to sort an integer array. Because arr10 and arr20 have different types, it is not possible to write a single procedure that will sort them both.The place where this affects Software Tools particularly, and I think programs in general, is that it makes it difficult indeed to create a library of routines for doing common, general-purpose operations like sorting.The particular data type most often affected is 'array of char', for in Pascal a string is an array of characters. Consider writing a function 'index(s,c)' that will return the position in the string s where the character c first occurs, or zero if it does not. The problem is how to handle the string argument of 'index'. The calls 'index('hello',c)' and 'index('goodbye',c)' cannot both be legal, since the strings have different lengths. (I pass over the question of how the end of a constant string like 'hello' can be detected, because it can't.) The next try is var temp : array [1..10] of char; temp := 'hello'; n := index(temp,c);but the assignment to 'temp' is illegal because 'hello' and 'temp' are of different lengths.The only escape from this infinite regress is to define a family of routines with a member for each possible string size, or to make all strings (including constant strings like 'define' ) of the same length.The latter approach is the lesser of two great evils. In 'Tools', a type called 'string' is declared as type string = array [1..MAXSTR] of char;where the constant 'MAXSTR' is ``big enough,'' and all strings in all programs are exactly this size. This is far from ideal, although it made it possible to get the programs running. It does not solve the problem of creating true libraries of useful routines.There are some situations where it is simply not acceptable to use the fixed-size array representation. For example, the 'Tools' program to sort lines of text operates by filling up memory with as many lines as will fit; its running time depends strongly on how full the memory can be packed.Thus for 'sort', another representation is used, a long array of characters and a set of indices into this array: type charbuf = array [1..MAXBUF] of char; charindex = array [1..MAXINDEX] of 0..MAXBUF;But the procedures and functions written to process the fixed-length representation cannot be used with the variable-length form; an entirely new set of routines is needed to copy and compare strings in this representation. In Fortran or C the same functions could be used for both.As suggested above, a constant string is written as 'this is a string'and has the type 'packed array [1..n] of char', where n is the length. Thus each string literal of different length has a different type. The only way to write a routine that will print a message and clean up is to pad all messages out to the same maximum length: error('short message '); error('this is a somewhat longer message');Many commercial Pascal compilers provide a 'string' data type that explicitly avoids the problem; 'string's are all taken to be the same type regardless of size. This solves the problem for this single data type, but no other. It also fails to solve secondary problems like computing the length of a constant string; another built-in function is the usual solution.Pascal enthusiasts often claim that to cope with the array-size problem one merely has to copy some library routine and fill in the parameters for the program at hand, but the defense sounds weak at best:(12)``Since the bounds of an array are part of its type (or, more exactly, of the type of its indexes), it is impossible to define a procedure or function which applies to arrays with differing bounds. Although this restriction may appear to be a severe one, the experiences we have had with Pascal tend to show that it tends to occur very infrequently. [...] However, the need to bind the size of parametric arrays is a serious defect in connection with the use of program libraries.''This botch is the biggest single problem with Pascal. I believe that if it could be fixed, the language would be an order of magnitude more usable. The proposed ISO standard for Pascal(13) provides such a fix (``conformant array schemas''), but the acceptance of this part of the standard is apparently still in doubt.2.2. There are no static variables and no initializationA 'static' variable (often called an 'own' variable in Algol-speaking countries) is one that is private to some routine and retains its value from one call of the routine to the next. De facto, Fortran variables are internal static, except for COMMON; in C there is a 'static' declaration that can be applied to local variables. (Strictly speaking, in Fortran 77 one must use SAVE to force the static attribute.)Pascal has no such storage class. This means that if a Pascal function or procedure intends to remember a value from one call to another, the variable used must be external to the function or procedure. Thus it must be visible to other procedures, and its name must be unique in the larger scope. A simple example of the problem is a random number generator: the value used to compute the current output must be saved to compute the next one, so it must be stored in a variable whose lifetime includes all calls of the random number generator. In practice, this is typically the outermost block of the program. Thus the declaration of such a variable is far removed from the place where it is actually used.One example comes from the text formatter described in Chapter 7 of 'Tools'. The variable 'dir' controls the direction from which excess blanks are inserted during line justification, to obtain left and right alternately. In Pascal, the code looks like this: program formatter (...); var dir : 0..1; { direction to add extra spaces } . . . procedure justify (...); begin dir := 1 - dir; { opposite direction from last time } ... end; ... begin { main routine of formatter } dir := 0; ... end;The declaration, initialization and use of the variable 'dir' are scattered all over the program, literally hundreds of lines apart. In C or Fortran, 'dir' can be made private to the only routine that needs to know about it: ... main() { ... } ... justify() { static int dir = 0; dir = 1 - dir; ... }There are of course many other examples of the same problem on a larger scale; functions for buffered I/O, storage management, and symbol tables all spring to mind.There are at least two related problems. Pascal provides no way to initialize variables statically (i.e., at compile time); there is nothing analogous to Fortran's DATA statement or initializers like int dir = 0;in C. This means that a Pascal program must contain explicit assignment statements to initialize variables (like the dir := 0;above). This code makes the program source text bigger, and the program itself bigger at run time.Furthermore, the lack of initializers exacerbates the problem of too-large scope caused by the lack of a static storage class. The time to initialize things is at the beginning, so either the main routine itself begins with a lot of initialization code, or it calls one or more routines to do the initializations. In either case, variables to be initialized must be visible, which means in effect at the highest level of the hierarchy. The result is that any variable that is to be initialized has global scope.The third difficulty is that there is no way for two routines to share a variable unless it is declared at or above their least common ancestor. Fortran COMMON and C's external static storage class both provide a way for two routines to cooperate privately, without sharing information with their ancestors.The new standard does not offer static variables, initialization or non-hierarchical communication.2.3. Related program components must be kept separateSince the original Pascal was implemented with a one-pass compiler, the language believes strongly in declaration before use. In particular, procedures and functions must be declared (body and all) before they are used. The result is that a typical Pascal program reads from the bottom up - all the procedures and functions are displayed before any of the code that calls them, at all levels. This is essentially opposite to the order in which the functions are designed and used.To some extent this can be mitigated by a mechanism like the #include facility of C and Ratfor: source files can be included where needed without cluttering up the program. #include is not part of standard Pascal, although the UCB, VU and Whitesmiths compilers all provide it.There is also a 'forward' declaration in Pascal that permits separating the declaration of the function or procedure header from the body; it is intended for defining mutually recursive procedures. When the body is declared later on, the header on that declaration may contain only the function name, and must not repeat the information from the first instance.A related problem is that Pascal has a strict order in which it is willing to accept declarations. Each procedure or function consists oflabel label declarations, if anyconst constant declarations, if anytype type declarations, if anyvar variable declarations, if anyprocedure and function declarations, if anybeginbody of function or procedureendThis means that all declarations of one kind (types, for instance) must be grouped together for the convenience of the compiler, even when the programmer would like to keep together things that are logically related so as to understand the program better. Since a program has to be presented to the compiler all at once, it is rarely possible to keep the declaration, initialization and use of types and variables close together. Even some of the most dedicated Pascal supporters agree:(14)``The inability to make such groupings in structuring large programs is one of Pascal's most frustrating limitations.''A file inclusion facility helps only a little here.The new standard does not relax the requirements on the order of declarations.2.4. There is no separate compilationThe ``official'' Pascal language does not provide separate compilation, and so each implementation decides on its own what to do. Some (the Berkeley interpreter, for instance) disallow it entirely; this is closest to the spirit of the language and matches the letter exactly. Many others provide a declaration that specifies that the body of a function is externally defined. In any case, all such mechanisms are non-standard, and thus done differently by different systems.Theoretically, there is no need for separate compilation - if one's compiler is very fast (and if the source for all routines is always available and if one's compiler has a file inclusion facility so that multiple copies of source are not needed), recompiling everything is equivalent. In practice, of course, compilers are never fast enough and source is often hidden and file inclusion is not part of the language, so changes are time-consuming.Some systems permit separate compilation but do not validate consistency of types across the boundary. This creates a giant hole in the strong typing. (Most other languages do no cross-compilation checking either, so Pascal is not inferior in this respect.) I have seen at least one paper (mercifully unpublished) that on page n castigates C for failing to check types across separate compilation boundaries while suggesting on page n+1 that the way to cope with Pascal is to compile procedures separately to avoid type checking.The new standard does not offer separate compilation.2.5. Some miscellaneous problems of type and scopeMost of the following points are minor irritations, but I have to stick them in somewhere.It is not legal to name a non-basic type as the literal formal parameter of a procedure; the following is not allowed: procedure add10 (var a : array [1..10] of integer);Rather, one must invent a type name, make a type declaration, and declare the formal parameter to be an instance of that type: type a10 = array [1..10] of integer; ... procedure add10 (var a : a10);Naturally the type declaration is physically separated from the procedure that uses it. The discipline of inventing type names is helpful for types that are used often, but it is a distraction for things used only once.It is nice to have the declaration 'var' for formal parameters of functions and procedures; the procedure clearly states that it intends to modify the argument. But the calling program has no way to declare that a variable is to be modified - the information is only in one place, while two places would be better. (Half a loaf is better than none, though - Fortran tells the user nothing about who will do what to variables.)It is also a minor bother that arrays are passed by value by default - the net effect is that every array parameter is declared 'var' by the programmer more or less without thinking. If the 'var' declaration is inadvertently omitted, the resulting bug is subtle.Pascal's 'set' construct seems like a good idea, providing notational convenience and some free type checking. For example, a set of tests like if (c = blank) or (c = tab) or (c = newline) then ...can be written rather more clearly and perhaps more efficiently as if c in [blank, tab, newline] then ...But in practice, set types are not useful for much more than this, because the size of a set is strongly implementation dependent (probably because it was so in the original CDC implementation: 59 bits). For example, it is natural to attempt to write the function 'isalphanum(c)' (``is c alphanumeric?'') as { isalphanum(c) -- true if c is letter or digit } function isalphanum (c : char) : boolean; begin isalphanum := c in ['a'..'z', 'A'..'Z', '0'..'9'] end;But in many implementations of Pascal (including the original) this code fails because sets are just too small. Accordingly, sets are generally best left unused if one intends to write portable programs. (This specific routine also runs an order of magnitude slower with sets than with a range test or array reference.)2.6. There is no escapeThere is no way to override the type mechanism when necessary, nothing analogous to the ``cast'' mechanism in C. This means that it is not possible to write programs like storage allocators or I/O systems in Pascal, because there is no way to talk about the type of object that they return, and no way to force such objects into an arbitrary type for another use. (Strictly speaking, there is a large hole in the type-checking near variant records, through which some otherwise illegal type mismatches can be obtained.)3. Control FlowThe control flow deficiencies of Pascal are minor but numerous - the death of a thousand cuts, rather than a single blow to a vital spot.There is no guaranteed order of evaluation of the logical operators 'and' and 'or' - nothing like && and || in C. This failing, which is shared with most other languages, hurts most often in loop control: while (i <= XMAX) and (x[i] > 0) do ...is extremely unwise Pascal usage, since there is no way to ensure that i is tested before x[i] is.By the way, the parentheses in this code are mandatory - the language has only four levels of operator precedence, with relationals at the bottom.There is no 'break' statement for exiting loops. This is consistent with the one entry-one exit philosophy espoused by proponents of structured programming, but it does lead to nasty circumlocutions or duplicated code, particularly when coupled with the inability to control the order in which logical expressions are evaluated. Consider this common situation, expressed in C or Ratfor: while (getnext(...)) { if (something) break rest of loop }With no 'break' statement, the first attempt in Pascal is done := false; while (not done) and (getnext(...)) do if something then done := true else begin rest of loop endBut this doesn't work, because there is no way to force the ``not done'' to be evaluated before the next call of 'getnext'. This leads, after several false starts, to done := false; while not done do begin done := getnext(...); if something then done := true else if not done then begin rest of loop end endOf course recidivists can use a 'goto' and a label (numeric only and it has to be declared) to exit a loop. Otherwise, early exits are a pain, almost always requiring the invention of a boolean variable and a certain amount of cunning. Compare finding the last non-blank in an array in Ratfor: for (i = max; i > 0; i = i - 1) if (arr(i) != ' ') breakwith Pascal: done := false; i := max; while (i > 0) and (not done) do if arr[i] = ' ' then i := i - 1 else done := true;The index of a 'for' loop is undefined outside the loop, so it is not possible to figure out whether one went to the end or not. The increment of a 'for' loop can only be +1 or -1, a minor restriction.There is no 'return' statement, again for one in-one out reasons. A function value is returned by setting the value of a pseudo-variable (as in Fortran), then falling off the end of the function. This sometimes leads to contortions to make sure that all paths actually get to the end of the function with the proper value. There is also no standard way to terminate execution except by reaching the end of the outermost block, although many implementations provide a 'halt' that causes immediate termination.The 'case' statement is better designed than in C, except that there is no 'default' clause and the behavior is undefined if the input expression does not match any of the cases. This crucial omission renders the 'case' construct almost worthless. In over 6000 lines of Pascal in 'Software Tools in Pascal', I used it only four times, although if there had been a 'default', a 'case' would have served in at least a dozen places.The new standard offers no relief on any of these points.4. The EnvironmentThe Pascal run-time environment is relatively sparse, and there is no extension mechanism except perhaps source-level libraries in the ``official'' language.Pascal's built-in I/O has a deservedly bad reputation. It believes strongly in record-oriented input and output. It also has a look-ahead convention that is hard to implement properly in an interactive environment. Basically, the problem is that the I/O system believes that it must read one record ahead of the record that is being processed. In an interactive system, this means that when a program is started, its first operation is to try to read the terminal for the first line of input, before any of the program itself has been executed. But in the program write('Please enter your name: '); read(name); ...read-ahead causes the program to hang, waiting for input before printing the prompt that asks for it.It is possible to escape most of the evil effects of this I/O design by very careful implementation, but not all Pascal systems do so, and in any case it is relatively costly.The I/O design reflects the original operating system upon which Pascal was designed; even Wirth acknowledges that bias, though not its defects.(15) It is assumed that text files consist of records, that is, lines of text. When the last character of a line is read, the built-in function 'eoln' becomes true; at that point, one must call 'readln' to initiate reading a new line and reset 'eoln'. Similarly, when the last character of the file is read, the built-in 'eof' becomes true. In both cases, 'eoln' and 'eof' must be tested before each 'read' rather than after.Given this, considerable pains must be taken to simulate sensible input. This implementation of 'getc' works for Berkeley and VU I/O systems, but may not necessarily work for anything else: { getc -- read character from standard input } function getc (var c : character) : character; var ch : char; begin if eof then c := ENDFILE else if eoln then begin readln; c := NEWLINE end else begin read(ch); c := ord(ch) end; getc := c end;The type 'character' is not the same as 'char', since ENDFILE and perhaps NEWLINE are not legal values for a 'char' variable.There is no notion at all of access to a file system except for predefined files named by (in effect) logical unit number in the 'program' statement that begins each program. This apparently reflects the CDC batch system in which Pascal was originally developed. A file variable var fv : file of typeis a very special kind of object - it cannot be assigned to, nor used except by calls to built-in procedures like 'eof', 'eoln', 'read', 'write', 'reset' and 'rewrite'. ('reset' rewinds a file and makes it ready for rereading; 'rewrite' makes a file ready for writing.)Most implementations of Pascal provide an escape hatch to allow access to files by name from the outside environment, but not conveniently and not standardly. For example, many systems permit a filename argument in calls to 'reset' and 'rewrite': reset(fv, filename);But 'reset' and 'rewrite' are procedures, not functions - there is no status return and no way to regain control if for some reason the attempted access fails. (UCSD provides a compile-time flag that disables the normal abort.) And since fv's cannot appear in expressions like reset(fv, filename); if fv = failure then ...there is no escape in that direction either. This straitjacket makes it essentially impossible to write programs that recover from mis-spelled file names, etc. I never solved it adequately in the 'Tools' revision.There is no notion of access to command-line arguments, again probably reflecting Pascal's batch-processing origins. Local routines may allow it by adding non-standard procedures to the environment.Since it is not possible to write a general-purpose storage allocator in Pascal (there being no way to talk about the types that such a function would return), the language has a built-in procedure called 'new' that allocates space from a heap. Only defined types may be allocated, so it is not possible to allocate, for example, arrays of arbitrary size to hold character strings. The pointers returned by 'new' may be passed around but not manipulated: there is no pointer arithmetic. There is no way to regain control if storage runs out.The new standard offers no change in any of these areas.5. Cosmetic IssuesMost of these issues are irksome to an experienced programmer, and some are probably a nuisance even to beginners. All can be lived with.Pascal, in common with most other Algol-inspired languages, uses the semicolon as a statement separator rather than a terminator (as it is in PL/I and C). As a result one must have a reasonably sophisticated notion of what a statement is to put semicolons in properly. Perhaps more important, if one is serious about using them in the proper places, a fair amount of nuisance editing is needed. Consider the first cut at a program: if a then b; c;But if something must be inserted before b, it no longer needs a semicolon, because it now precedes an 'end': if a then begin b0; b end; c;Now if we add an 'else', we must remove the semicolon on the 'end': if a then begin b0; b end else d; c;And so on and so on, with semicolons rippling up and down the program as it evolves.One generally accepted experimental result in programmer psychology is that semicolon as separator is about ten times more prone to error than semicolon as terminator.(16) (In Ada,(17) the most significant language based on Pascal, semicolon is a terminator.) Fortunately, in Pascal one can almost always close one's eyes and get away with a semicolon as a terminator. The exceptions are in places like declarations, where the separator vs. terminator problem doesn't seem as serious anyway, and just before 'else', which is easy to remember.C and Ratfor programmers find 'begin' and 'end' bulky compared to { and }.A function name by itself is a call of that function; there is no way to distinguish such a function call from a simple variable except by knowing the names of the functions. Pascal uses the Fortran trick of having the function name act like a variable within the function, except that where in Fortran the function name really is a variable, and can appear in expressions, in Pascal, its appearance in an expression is a recursive invocation: if f is a zero-argument function, 'f:=f+1' is a recursive call of f.There is a paucity of operators (probably related to the paucity of precedence levels). In particular, there are no bit-manipulation operators (AND, OR, XOR, etc.). I simply gave up trying to write the following trivial encryption program in Pascal: i := 1; while getc(c) <> ENDFILE do begin putc(xor(c, key[i])); i := i mod keylen + 1 endbecause I couldn't write a sensible 'xor' function. The set types help a bit here (so to speak), but not enough; people who claim that Pascal is a system programming language have generally overlooked this point. For example, [18, p. 685]``Pascal is at the present time [1977] the best language in the public domain for purposes of system programming and software implementation.''seems a bit naive.There is no null string, perhaps because Pascal uses the doubled quote notation to indicate a quote embedded in a string: 'This is a '' character'There is no way to put non-graphic symbols into strings. In fact, non-graphic characters are unpersons in a stronger sense, since they are not mentioned in any part of the standard language. Concepts like newlines, tabs, and so on are handled on each system in an 'ad hoc' manner, usually by knowing something about the character set (e.g., ASCII newline has decimal value 10).There is no macro processor. The 'const' mechanism for defining manifest constants takes care of about 95 percent of the uses of simple #define statements in C, but more involved ones are hopeless. It is certainly possible to put a macro preprocessor on a Pascal compiler. This allowed me to simulate a sensible 'error' procedure as #define error(s)begin writeln(s); halt end('halt' in turn might be defined as a branch to the end of the outermost block.) Then calls like error('little string'); error('much bigger string');work since 'writeln' (as part of the standard Pascal environment) can handle strings of any size. It is unfortunate that there is no way to make this convenience available to routines in general.The language prohibits expressions in declarations, so it is not possible to write things like const SIZE = 10; type arr = array [1..SIZE+1] of integer;or even simpler ones like const SIZE = 10; SIZE1 = SIZE + 1;6. PerspectiveThe effort to rewrite the programs in 'Software Tools' started in March, 1980, and, in fits and starts, lasted until January, 1981. The final product(19) was published in June, 1981. During that time I gradually adapted to most of the superficial problems with Pascal (cosmetics, the inadequacies of control flow), and developed imperfect solutions to the significant ones (array sizes, run-time environment).The programs in the book are meant to be complete, well-engineered programs that do non-trivial tasks. But they do not have to be efficient, nor are their interactions with the operating system very complicated, so I was able to get by with some pretty kludgy solutions, ones that simply wouldn't work for real programs.There is no significant way in which I found Pascal superior to C, but there are several places where it is a clear improvement over Ratfor. Most obvious by far is recursion: several programs are much cleaner when written recursively, notably the pattern-search, quicksort, and expression evaluation.Enumeration data types are a good idea. They simultaneously delimit the range of legal values and document them. Records help to group related variables. I found relatively little use for pointers.Boolean variables are nicer than integers for Boolean conditions; the original Ratfor programs contained some unnatural constructions because Fortran's logical variables are badly designed.Occasionally Pascal's type checking would warn of a slip of the hand in writing a program; the run-time checking of values also indicated errors from time to time, particularly subscript range violations.Turning to the negative side, recompiling a large program from scratch to change a single line of source is extremely tiresome; separate compilation, with or without type checking, is mandatory for large programs.I derived little benefit from the fact that characters are part of Pascal and not part of Fortran, because the Pascal treatment of strings and non-graphics is so inadequate. In both languages, it is appallingly clumsy to initialize literal strings for tables of keywords, error messages, and the like.The finished programs are in general about the same number of source lines as their Ratfor equivalents. At first this surprised me, since my preconception was that Pascal is a wordier and less expressive language. The real reason seems to be that Pascal permits arbitrary expressions in places like loop limits and subscripts where Fortran (that is, portable Fortran 66) does not, so some useless assignments can be eliminated; furthermore, the Ratfor programs declare functions while Pascal ones do not.To close, let me summarize the main points in the case against Pascal.Since the size of an array is part of its type, it is not possible to write general-purpose routines, that is, to deal with arrays of different sizes. In particular, string handling is very difficult.The lack of static variables, initialization and a way to communicate non-hierarchically combine to destroy the ``locality'' of a program - variables require much more scope than they ought to.The one-pass nature of the language forces procedures and functions to be presented in an unnatural order; the enforced separation of various declarations scatters program components that logically belong together.The lack of separate compilation impedes the development of large programs and makes the use of libraries impossible.The order of logical expression evaluation cannot be controlled, which leads to convoluted code and extraneous variables.The 'case' statement is emasculated because there is no default clause.The standard I/O is defective. There is no sensible provision for dealing with files or program arguments as part of the standard language, and no extension mechanism.The language lacks most of the tools needed for assembling large programs, most notably file inclusion.There is no escape.This last point is perhaps the most important. The language is inadequate but circumscribed, because there is no way to escape its limitations. There are no casts to disable the type-checking when necessary. There is no way to replace the defective run-time environment with a sensible one, unless one controls the compiler that defines the ``standard procedures.'' The language is closed.People who use Pascal for serious programming fall into a fatal trap.Because the language is so impotent, it must be extended. But each group extends Pascal in its own direction, to make it look like whatever language they really want. Extensions for separate compilation, Fortran-like COMMON, string data types, internal static variables, initialization, octal numbers, bit operators, etc., all add to the utility of the language for one group, but destroy its portability to others.I feel that it is a mistake to use Pascal for anything much beyond its original target. In its pure form, Pascal is a toy language, suitable for teaching but not for real programming.AcknowledgmentsI am grateful to Al Aho, Al Feuer, Narain Gehani, Bob Martin, Doug McIlroy, Rob Pike, Dennis Ritchie, Chris Van Wyk and Charles Wetherell for helpful criticisms of earlier versions of this paper.[1]Feuer, A. R. and N. H. Gehani, ``A Comparison of the Programming Languages C and Pascal - Part I: Language Concepts,'' Bell Labs internal memorandum (September 1979).[2]N. H. Gehani and A. R. Feuer, ``A Comparison of the Programming Languages C and Pascal - Part II: Program Properties and Programming Domains,'' Bell Labs internal memorandum (February 1980).[3]P. Mateti, ``Pascal versus C: A Subjective Comparison,'' Language Design and Programming Methodology Symposium, Springer-Verlag, Sydney, Australia (September 1979).[4]A. Springer, ``A Comparison of Language C and Pascal,'' IBM Technical Report G320-2128, Cambridge Scientific Center (August 1979).[5]B. W. Kernighan and P. J. Plauger, Software Tools, Addison-Wesley, Reading, Mass. (1976).[6]K. Jensen, Pascal User Manual and Report, Springer-Verlag (1978). (2nd edition.)[7]David V. Moffat, ``A Categorized Pascal Bibliography,'' SIGPLAN Notices 15(10), pp. 63-75 (October 1980).[8]A. N. Habermann, ``Critical Comments on the Programming Language Pascal,'' Acta Informatica 3, pp. 47-57 (1973).[9]O. Lecarme and P. Desjardins, ``More Comments on the Programming Language Pascal,'' Acta Informatica 4, pp. 231-243 (1975).[10]H. J. Boom and E. DeJong, ``A Critical Comparison of Several Programming Language Implementations,'' Software Practice and Experience 10(6), pp. 435-473 (June 1980).[11]N. Wirth, ``An Assessment of the Programming Language Pascal,'' IEEE Transactions on Software Engineering SE-1(2), pp. 192-198 (June, 1975).[12]O. Lecarme and P. Desjardins, ibid, p. 239.[13]A. M. Addyman, ``A Draft Proposal for Pascal,'' SIGPLAN Notices 15(4), pp. 1-66 (April 1980).[14]J. Welsh, W. J. Sneeringer, and C. A. R. Hoare, ``Ambiguities and Insecurities in Pascal,'' Software Practice and Experience 7, pp. 685-696 (1977).[15]N. Wirth, ibid., p. 196.[16]J. D. Gannon and J. J. Horning, ``Language Design for Programming Reliability,'' IEEE Trans. Software Engineering SE-1(2), pp. 179-191 (June 1975).[17]J. D. Ichbiah, et al, ``Rationale for the Design of the Ada Programming Language,'' SIGPLAN Notices 14(6) (June 1979).[18]J. Welsh, W. J. Sneeringer, and C. A. R. Hoare, ibid.[19]B. W. Kernighan and P. J. Plauger, Software Tools in Pascal, Addison-Wesley (1981).

主题推荐
语言operating system计算机科学解决方案transactions
猜你在找
Checking operating system version: must be redhat-3, SuSE-9, redhat-4, UnitedLinux-1.0, asianux-1 or
2014-3-31~2014-4-6工作总结
[GitHub][2014-05-11 23:19:44]FAST-FW
开始时间设置为2014-04-12 00:00:00格式,结束时间设置为2014-04-12 23:59:59 格式
[GitHub][2014-05-11 23:20:17]flexbison
启动oracle11g数据库报memory_target not supported on this system错解决方案
2014/04/11
Oracle 11g 安装时常见异常信息及解决方案
普适计算-2014/04/11
关于Tomcat搭建服务器需要80端口问题的解决方案以及80端口被NT KERNEL & SYSTEM ,pid4占用解决方法
查看评论

  暂无评论

发表评论
  • 用 户 名:
  • zzwu
  • 评论内容:
  • 插入代码
  •   
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
快速回复TOP
核心技术类目
全部主题 Hadoop AWS 移动游戏 Java Android iOS Swift 智能硬件 Docker OpenStackVPN Spark ERP IE10 Eclipse CRM JavaScript 数据库 Ubuntu NFC WAP jQueryBI HTML5 Spring Apache .NET API HTML SDK IIS Fedora XML LBS UnitySplashtop UML components Windows Mobile Rails QEMU KDE Cassandra CloudStack FTCcoremail OPhone CouchBase 云计算 iOS6 Rackspace Web App SpringSide MaemoCompuware 大数据 aptech Perl Tornado Ruby Hibernate ThinkPHP HBase Pure SolrAngular Cloud Foundry Redis Scala Django Bootstrap

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. PRO/E配置文件选项

    关于配置文件选项为配置文件输入所需的设置&#xff0c;可以预设环境选项和其它全局设置。要设置配置文件选项&#xff0c;使用“选项”对话框&#xff08;“实用工具”>“选项”&#xff09;。本帮助模块含有一个按字母顺序显示每一选项或相关选项组的配置选项列表&#xf…...

    2024/5/7 5:57:54
  2. Python总复习-下

    目录 人工智能总目录网页链接 文章目录目录9、Python-web前端Day01-HTML-页面1. Web1. 什么是WEB2. 组成3. Web 服务器4. 浏览器2. HTML 概述1.HyperText Markup Language2. 标记3. 网页3. HTML基础语法1. 标签/标记2. HTML标签介绍3. 完整的网页结构4. 网页头部设置5. 网页主…...

    2024/4/23 3:29:10
  3. 关于一个递归逻辑的代码优化建议

    1.需求说明 刚接手一个项目&#xff0c;有个文件上传分类功能&#xff0c;但每次只能操作一个文件&#xff0c;测试需要几十个上百个文件&#xff0c;效率实在太低了。 于是让公司小弟改为可以支持批量上传&#xff0c;小弟在写的时候&#xff0c;发现后端只能一个文件处理结…...

    2024/4/29 3:01:56
  4. JS中使用FormData上传文件、图片的方法

    参考博客&#xff1a;http://www.cnblogs.com/xiaohuochai/p/6543019.htmlhttp://www.cnblogs.com/qcloud1001/p/6839541.html 使用CORS 实现Ajax的另类跨域:关于浏览器端&#xff0c;以jQuery为例&#xff0c;我们需要在ajax请求中加一个参数xhrFields&#xff0c;并设置为wit…...

    2024/5/7 9:40:38
  5. 手把手教你如何利用阿里云上传文件

    最近由于公司业务需要&#xff0c;我需要使用阿里云来保存视频文件。然后访问的话需要一个临时的url可供使用&#xff0c;这样不用担心长时间暴露签名信息和地址。但是完全没做过这个东西&#xff0c;心里是慌得一笔。手动滑稽~~~。但是也是没办法&#xff0c;硬着头皮冲啦~ 不…...

    2024/4/21 3:26:28
  6. 常见面试题总结

    参考&#xff1a; https://www.nowcoder.com/ta/front-end-interview?query&asctrue&order&tagQuery&page1 http://bigerfe.com/ https://blog.csdn.net/keyandi/article/details/89227175 https://blog.csdn.net/MingL520/article/details/88549999 https:/…...

    2024/4/21 3:26:26
  7. Elastic Search + Logstash + Kibana 初学者日志

    ELK下载https://www.elastic.co/downloads因为我用的是windows操作系统&#xff0c;所以下面的介绍都基于windows环境。功能方面应该和Linux是一样的。Getting Started with ELK for Apache Logs (这个例子展示了怎样用logstash把log发送到Elastic Search, 然后用Kibana做图形化…...

    2024/5/7 1:43:33
  8. 从零开始配置 TypeScript 项目

    关于作者本文出自于掘金的子弈&#xff0c;原文链接 从零开始配置 TypeScript 项目。以下是他的一些不错的作品&#xff0c;感兴趣的可以阅读&#xff1a;面试分享&#xff1a;两年工作经验成功面试阿里P6总结在阿里我是如何当面试官的如果觉得不错希望能够在掘金关注、点赞哦&…...

    2024/5/7 8:58:19
  9. 从JavaScript到TypeScript,Pt。 IIB:使用类,接口和混合器进行设计

    Class-based design has become such an instinct that many developers cant imagine any alternative. 基于类的设计已经成为一种本能&#xff0c;许多开发人员无法想象任何替代方案。 Fortunately for that lot, ES6 adds a class keyword to simplify the syntactical cac…...

    2024/5/6 20:31:26
  10. ROS学习笔记(三)先锋机器人的使用 — 参考 ROS wiki 和 Mobile wiki

    –参考方案&#xff1a; 找到了关于p3-dx的一些关于ROS的资料 https://github.com/ManolisCh/pioneer_p3dx https://github.com/SeRViCE-Lab/p3-dx http://wiki.ros.org/demo_pioneer 先锋机器人ROS的教程&#xff1a; https://www.youtube.com/watch?v-9NHupBPC6Y 首先…...

    2024/5/7 1:02:57
  11. 第七次迭代开发总结(AngularJS下文件上传的实现)

    第七次迭代开发总结 突然之间冒出来一个第七次迭代总结看上去挺奇怪的&#xff0c;事实上因为学校项目的关系&#xff0c;我暑假留校继续开发。在迭代的前半周期&#xff0c;团队进行了一次技术迁移&#xff0c;舍弃LiveScript转向了ECMAScript 6。有空的话会写一些ECMAScript…...

    2024/5/5 18:34:01
  12. “JavaScript Promises和AngularJS $q Service”Part 2 (教程篇)

    欢迎大家到我的博客关注我学习Ionic 1和Ionic 2的历程&#xff0c;共同学习&#xff0c;共同进步。 注&#xff1a;本文是译文&#xff0c;难免有错误或理解不足之处&#xff0c;请大家多多指正&#xff0c;大家也可挪步原文。由于本文讲解十分精彩&#xff0c;非常推荐大家查看…...

    2024/4/28 20:32:58
  13. HEVC相关文档

    转载自 ye_f最终编辑 ye_f虽然也是做编码的&#xff0c;让自己懒得写啊&#xff0c;一下材料源自http://blog.csdn.net/yuanchao99/article/details/6803856&#xff0c;谢谢啊。 •ITU官网&#xff1a; –http://www.itu.int/itu-t/workprog/wp_item.aspx?isn7752•会议文档&…...

    2024/4/21 3:26:19
  14. angularJS关于依赖和模块与amd/cmd的区别,分享下结合使用示例

    angular框架的介绍大家可以参考下官网和中文社区。 下面链接是简介&#xff1a; http://www.angularjs.cn/docs/developer/328.html 简单总结下就是&#xff1a; 双向绑定&#xff0c;可测试性的代码结构&#xff0c;模型视图分离的一个前端MV*框架 其中angular也提供了模型的概…...

    2024/5/7 9:06:06
  15. angularjs完整demo例子

    AngularJS的主要特点是 mvc 数据双向绑定 分模块 依赖注入    mvc m: $Scope 变量 V:视图 c:controllerfunction(){} 控制器 方法    Angularjs的用法 1.在一个有起始标签的元素开始标签内使用 ng-app来指定angularjs的作用范围 2.angularJS的表达式是双大括号 {{}} 里…...

    2024/5/7 4:24:48
  16. x265-1.8版本-x265.h代码注释

    注&#xff1a;问号以及未注释部分 会在x265-1.9版本内更新 /****************************************************************************** Copyright (C) 2013 x265 project** Authors: Steve Borho <steveborho.org>** This program is free software; you can …...

    2024/4/19 22:05:24
  17. angular6学习(九):数据绑定到事件

    实现功能&#xff1a;将html页面中文本框的输入的内容传递到ts文件&#xff0c;然后在html文件中显示ts文件中的这个内容。 html文件 一、绑定到事件 ts文件 显示结果&#xff1a; 二、双向绑定&#xff1a; html: app.module.ts...

    2024/4/20 20:07:11
  18. Angular数据绑定

    Angular的数据绑定分为三种&#xff1a; < h1> {{变量名}} </h1>&#xff1a;插值表达式&#xff08;单向绑定&#xff09;< img [src]"imgUrl"> :属性绑定<button (click)"toPrduct($event)">: 事件绑定($event是一个事件变量) …...

    2024/4/20 20:07:10
  19. Angular10 数据绑定

    Angular10数据绑定 中文官网地址 绑定方式 绑定类型语法分类举例插值、属性、attribute、css类、样式{{expression}}[target] expression’bind-target‘expression’单向从数据源到视图数据绑定{{title}}事件(target)statement’on-target‘statement’单向从视图到数据源的…...

    2024/4/20 20:07:09
  20. Angular如何给动态生成的元素绑定事件

    在AngularJS中&#xff0c;操作DOM一般在指令中完成&#xff0c;事件监听机制是在对于已经静态生成的dom绑定事件&#xff0c;而如果在指令中动态生成了DOM节点&#xff0c;动态生成的节点不会被JS事件监听。 举例来说&#xff1a; angular.module(myapp,[]) .directive(myText…...

    2024/4/21 3:26:16

最新文章

  1. React 第二十三章 shouldComponentUpdate

    React 中的 shouldComponentUpdate 是一个生命周期方法&#xff0c;用于控制组件是否需要重新渲染。 文档地址&#xff1a;https://zh-hans.reactjs.org/docs/react-component.html#shouldcomponentupdate shouldComponentUpdate 接收两个参数&#xff1a;nextProps 和 nextS…...

    2024/5/7 10:35:10
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 整理的微信小程序日历(单选/多选/筛选)

    一、日历横向多选&#xff0c;支持单日、双日、三日、工作日等选择 效果图 wxml文件 <view class"calendar"><view class"section"><view class"title flex-box"><button bindtap"past">上一页</button&…...

    2024/5/5 8:50:30
  4. c++类的继承方式

    在 C 中&#xff0c;类的继承方式有三种&#xff1a;公有继承&#xff08;public inheritance&#xff09;、保护继承&#xff08;protected inheritance&#xff09;和私有继承&#xff08;private inheritance&#xff09;。这些继承方式决定了派生类对基类成员的访问权限。 …...

    2024/5/3 14:42:38
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/7 5:50:09
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/7 9:45:25
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/6 9:21:00
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/6 21:42:42
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57