Why did we bother with line numbers at all?
当你写一些基本的东西时,你需要使用行号。像:
1 2 3 | 10 PRINT"HOME" 20 PRINT"SWEET" 30 GOTO 10 |
但我想知道:到底是谁想出了使用行号的主意?这真是令人讨厌,在发展中(双关语)世界留下了相当多的"回音"!
当时的想法是,通过使用适当的行号,可以很容易地在程序中的任何地方添加代码。这就是为什么每个人都用10、20、30号线。所以还有空间:
1 2 3 4 | 10 PRINT"HOME" 20 PRINT"SWEET" 30 GOTO 10 25 PRINT"HOME" |
在第一个基本接口上,没有闪亮的编辑器,甚至没有像vi或emacs(或dos edit,heh)这样的东西。您只能在控制台上打印出您的程序,然后您将添加新行或替换它们,方法是先给出适当的行号。你不能像现在这样用光标浏览"文件"(程序保存在内存中,尽管你可以在磁盘上保存一份副本)。
因此,行号不仅需要作为臭名昭著的goto的标签,而且确实需要告诉解释器您正在编辑的程序流中的哪个位置。
它有着悠久的历史。
行编号实际上来自达特茅斯基本语言,它是基本编程语言的原始版本,是所谓达特茅斯分时系统的组成部分。DTS有一个基本的IDE,它只不过是一个交互式命令行。
因此,在这个"ide"中键入的每一行(以行号开始)都被添加到程序中,用相同的编号替换先前存储的任何行;其他任何行都被假定为DTSS命令并立即执行。
在出现视频显示终端(vdt)之前,我们用打孔卡编程。穿孔卡片为序列号保留了72-80列-如果您丢弃了卡片组,而它们都不正常,您可以将卡片组放在卡片分类机中,根据这些序列号对卡片进行排序。在许多方面,基本行号与序列号相似。
在基础世界的另一个优势是,在过去,基础被解释为它的运行。对分支使用标签而不是连续的行号将需要第一次传递来获取所有标签及其位置,在这种情况下,就像使用行号一样,解释器知道它是否需要开始向前或向后扫描目的地。
以前你没有像emacs或vi这样的二维编辑器,你只有命令行。
您的程序存储在内存中,您可以输入单行命令来编辑单行。
如果你是一个Unix的上帝,你可以用Ed或者其他东西来做,但是对于C-64、VIC-20或者TRS-80上的基本功能,你只需要重写这行。
所以一个会话可能看起来像:
1 2 3 | $10 PRINT"Hellow World" $20 GOTO 10 $10 PRINT"Hello World" |
现在程序可以正常工作了。
一些老式主机甚至有没有屏幕的线路终端。你的整个课程都用墨水印在纸上了!
"谁?"会是发明家,凯门尼和库尔茨。
在阅读了这些回复之后,我检查了维基百科的"达特茅斯基础"条目,并惊讶地发现
The first compiler was produced before the time-sharing system was ready. Known as CardBASIC, it was intended for the standard card-reader based batch processing system.
所以,看起来保罗·汤布林"站得住脚"。
它们起源于Fortran,从中派生出basic。然而,在Fortran中,只有其他行(如goto目标)引用的行需要数字。基本上,它们有第二个用途,即允许编辑特定的行。
PaulTomblin的回答是最全面的,但是我很惊讶没有人提到基本项目的初始目标的很大一部分是使用分时提供一个初学者友好的交互环境。(在这方面,库尔茨和凯门尼的"所有学生普遍入学"愿景远远领先于当时。)
为实现这一目标而开发的基本系统是电传打字机ASR-33(以及后来的其他)打印终端。当连接到具有分时功能的操作系统时,这些操作系统允许在交互模式下编辑和运行基本程序(与使用穿孔卡不同),但它们不是光标可寻址的。行号是一种初学者友好的方式,既可以指定程序语句的顺序,也可以在没有屏幕编辑器的情况下进行明确的编辑。维基百科中的"行编辑器"进一步解释了这一点,任何曾经尝试过使用行编辑器的人(如un*x'ed)都能理解为什么要感谢Kurtz和Kemeny,因为初学者不必学习用这种方式编辑文本所需的神秘命令序列。
我猜它来自汇编程序,每个指令都有一个地址,可以被另一个指令跳转到该地址。
另外,第一台计算机内存不足,存储行号只需要两个字节(如果操作得当)。写标签需要更多的内存,首先是在定义标签的位置,然后是在任何跳转命令中。
最后,在过去的好日子里,没有任何花哨的编辑。唯一的"编辑器"是一个简单的命令行界面,它将所有以数字开头的内容作为程序的一部分,而其他内容则作为命令立即执行。最突出的例子应该是准将64。
新的基本方言不再需要行号了。
早在50年代,当高级编程语言刚刚起步时,就没有终端、编辑器、监视器(是的,没有监视器),只有卡片穿孔机和读卡器(用于将卡片内容写入和读取到计算机内存中)和打印机(自然地,用于打印结果)。后来,磁带被引进了,但那是另一个故事。
每张打孔卡都有自己的号码。原因有几个:从单纯地保持秩序到决定执行的顺序。每张卡片都是一行代码(按今天的术语)。因为当时没有像if..then..else或类似的任何变体这样的构造,所以必须以某种方式确定执行顺序。所以我们引入了goto语句。它们是循环的基础。术语"意大利面代码"也来自那个时期,因为写得不好的代码相对来说很难遵循,就像盘子里的意大利面一样:)
基本上,如果没有行号,如何执行
1 | GOTO 10 |
这是一种跳线的方法,一种很好的方法…20多年前!
今天,这些行帮助我们捕获错误/异常,因为调试引擎会向我们发送消息,告诉我们在第xxx行上得到了异常,然后我们立即跳到它上面!
想象一个没有行号的世界…记者没有台词怎么付钱?
"Now that you know the novel, you have to write a summary with no more than 50 lines"
还记得这个吗?即使在学校里,我们也会学习行号!
如果它不是被发明出来的,有人会再次发明的,这样我们就可以很好地使用它了。)
并非所有版本的基本必需行号。例如,QBasic支持的标签。然后你可以跳到那些有go to的人身上(暂时忽略dijkstra的"Go-to声明被认为是有害的")。
答案已经在上面了。保罗·汤布林写了这封信(但要注意扎布佐克)。
事实上,我认为任何没有提到"打孔卡"的答案都是不完整的,如果它既没有提到打孔卡,也没有提到Fortran,那就错了。我可以说这是绝对正确的,因为我的父母都定期使用穿孔卡片(他们从Fortran 66和77开始),然后在80年代迁移到basic和cobol。
在早期,大多数程序都是用穿孔卡片输入的。穿孔卡片通常按顺序输入,通常每个卡片一条指令,标签(jmp/jsr目标)是一个单独的指令卡。
要编辑您的程序,您更换了卡。
后来的实现在行的右端添加了一个可选的序列号,这样当/如果顺序不对时,可以由自动读卡器对其重新排序。
Fortran在左边(col 1-5)和左边(73-80)都使用了数字目标标签作为序列或注释。
当basic最初被写入时,它决定将序列号向左移动到fortran的label字段中,并允许覆盖以前的卡的内存占用…作为编辑模式。这是为交互开发环境而设计的,但也适用于卡片。由于各种原因,在一些早期的实现中使用了卡片。
请记住:在20世纪70年代末,许多计算机都是读卡器和打印机接口。即使有THO的交互模式基础,也经常使用穿孔基本程序。因为许多人只是在向IDE进餐,所以他们的工作方式完全相同。包括最后需要一张"运行"卡。在这种情况下,可以简单地添加一张校正卡和另一张运行卡,在某个变量上添加一个变量来重新运行;同样,在复杂的程序中,只需在运行前添加一行校正卡,就可以在不花费宝贵时间查找出错卡本身的情况下编辑问题。
我喜欢Futurama的机器人教堂,墙上写着
1 2 | 10 SIN 20 GOTO HELL |
在specy上,没有行号就不能编辑行。
配对时我发现它们非常有用。当我的搭档有键盘时,我不必指着一行,我可以说,"在第74行,这不是真的是getmorebeer()吗?"
DOS的原始编辑是一个很棒的实用程序,叫做Edlin。只能编辑一行。为了让生活在许多基本版本中变得更有趣,您可以输入无序的行,行10、20、30、25、5,执行将按行编号,而不是按外观顺序。