奇奇怪怪的知识增加了,大括号的历史你知道吗?

编程史上大括号的演变
从Fortran到Algol,再到BCPL和C语言,大括号在编程语言中的角色经历了从无到有,从单词标记到符号标记的转变。这一变化不仅反映了编程结构的进化,也体现了对代码清晰性和效率的追求。


作者 | Michael McMillan

译者 | 弯月,责编 | 夕颜

封图 | 优快云下载自视觉中国

出品 | 优快云(ID:优快云news)

众所周知的标志代码块起始和结尾的大括号是什么时候开始成为编程语言的一部分的呢?或者更重要的是,代码块何时成了编程结构的重要组成部分?

 

我希望通过本文回答这些问题。

无代码块的语言

 

熟悉C语言语法风格的程序员都对编程块很熟悉。C、C++、Java、JavaScript以及许多其他语言中,所有主要编程结构都是代码块。换句话说,这些编程结构都被放到了代码块中,而代码块的标志就是起始和结尾的大括号。

 

严格来说这并不完全正确,例如if语句和循环这两种结构,如果其主体部分只包含一条语句,那么可以不使用代码块。但是,在过去几年,编程风格的专家们都建议所有编程结构的主体都应该放在代码块中(参见Douglas Cockroft的《JavaScript语言精粹》一书,其中的解释更具说服力)。

 

但是,第一个高级编程语言并没有代码块。

 

我以上世纪五十年代时的FORTRAN语言为例说明。高德纳在他那篇针对早期高级语言的评论《The Early Development of Programming Languages》(该文章在他的书《Selected Papers on Computer Languages》一书中重印)中比较了几个早期编程语言的特性。他的比较方法是演示某段程序用几种语言怎样编写。这段程序实现了一个叫做TPK的算法,我们来看看用现代的JavaScript怎样编写:

 

你不必在意这段程序的功能。这里的重点是,这段程序展示了高德纳认为的现代编程语言中的所有重要特性。

 

我前面说过,高德纳使用该算法比较了几种编程语言,其中一种语言就是现在人们公认的第一个真正的高级语言。下面是高德纳编写的用Fortran语言实现的TPK算法:

 

我不想详细介绍Fortran的语法,但你可以很清晰地看到,该语言没有代码块。函数定义在某一行上,而不是定义成了一个块。DO循环使用行标号来控制循环。当时的高级语言还没有将组合语句分组成代码块的概念,所以这些语言依然需要依赖goto来控制程序流程。

 

这段代码是高德纳使用1957年的Fortran编写的。在1957~1960年之间,一种新的语言出现了,那就是ALGOL,它弥补了许多Fortran等高级语言的不足之处。

ALGOL中的代码块

 

ALGOL编程语言于1958年首次提出,尽管最流行的版本是Algol 60。Algol语言的特性之一就是能够将语句分组,变成组合语句,也叫代码块。每个Algol程序都可以认为是一个代码块,因为程序通常包含一条或多条语句(因此称为“组合语句”)。Algol的开发者认为,许多编程场景(如条件判断和循环)都需要将多条语句作为一个整体考虑。

 

Algol使用关键字begin和end表示代码块的开始和结束。代码块可以嵌套在其他代码块中,外部的代码块叫做主代码块,而内部的代码块叫做子代码块。例如,下面这段Algol程序就包含嵌套的代码块:

 

该程序将会按照顺序输出数字2和1。

 

下面是在Algol的if语句中使用代码块的例子:

 

下面是在Algol的for语句中使用代码块的例子:

 

下面来看看使用Algol语言编写的TPK程序,可以看到,与Fortran相比,代码块结构可以让程序更清晰:

 

可以看出,Algol的代码块结构让程序更像我们今天使用的语言。

转向BCPL

 

块结构语言语法的下一个改变就是Martin Richards于1967年在剑桥大学发明的BCPL语言。在1960~1967年间Algol语言开发的初始阶段,编译器开发者和系统开发者一直在寻找一种方法,使用机器语言和汇编语言之外的语言来开发系统程序(如操作系统)。之所以这里强调BCPL,是因为它发展和精炼后变成了由Ken Thompson发明的B语言,后来又发展成了C语言。

 

Richards开发的BCPL语言是一种系统语言,它有汇编语言同样的效率,但语法更像Algol等高级语言,所以编写程序更容易,效率也更高。这意味着Algol等高级语言的许多特性必须用一种更高效的方式包含在BCPL中。

 

实现这种高效的方式之一就是将代码块的标志从单词(begin和end)改成符号。对于组合语句和代码块,Richards建议使用符号$(和)$作为开始和结束标记。这些符号称为“节括号”。

 

在BCPL中,如果将$(和)$与if语句或循环等结构一起使用,则它们表示一个组合语句。如果$(包含一些定义,则它们表示一个代码块。

 

例如,下面是在BCPL中使用if语句和组合语句的例子:

 

下面是BCPL代码块的例子:

 

这里,起始记号表示代码块的开始,因为它后面紧跟着声明。

 

$(和$)变成了C语言中的大括号

 

在1968年或1969年前后,贝尔实验室的Ken Thompson和Dennis Ritchie开始使用系统编程语言开发操作系统。实际上,Thompson最初想使用Fortran,但很快就放弃了,因为他发现Fortran无法实现。因此他决定修改BCPL语言来创造一种更合适的系统语言,于是B语言诞生了。

 

尽管B语言更接近Thompson和Ritchie想要的系统语言,但仍然无法完全满足要求,于是Ritchie开始开发另一种语言,称为NB,意思是New B。NB并没有存活太久,最终被另一种全新的语言代替,这个全新的语言最后被称为C。如果你对C语言如何从BCPL、B和NB发函而来,我建议你阅读一下Dennis Ritchie的《History of the C Language》。

 

许多从B语言中继承到NB再继承到C语言中的特性,都经过了Thompson的修改,其中之一就是操作符缩写。为了将语言放入当时内存十分有限的计算机中,这些修改是必须的。例如,Thompson创造了组合赋值运算符(如+=)和自增(++)和自减(--)运算符,以便让语言更有效率。这也导致BCPL中的其他符号被简化,如$(和)$就被改成了{和}。

 

现状

 

今天的许多语言已经采用大括号作为代码块的主要标志,特别是那些接近C风格的语言,如C++、Java、C#和JavaScript。

 

更有意思的是,新的语言也采用了大括号,如Go和Rust。实际上,Go语言要求每个条件语句或循环结构都使用大括号,这遵循了编程专家们的建议:即使不必要,每个结构也都应该使用大括号。

原文链接:

https://medium.com/better-programming/a-brief-history-of-the-curly-brace-in-programming-5b3eacdc3f7a

本文为优快云翻译文章,转载请注明出处。

【END】

今日福利

遇见陆奇

同样作为“百万人学 AI”的重要组成部分,2020 AIProCon 开发者万人大会将于 7 月 3 日至 4 日通过线上直播形式,让开发者们一站式学习了解当下 AI 的前沿技术研究、核心技术与应用以及企业案例的实践经验,同时还可以在线参加精彩多样的开发者沙龙与编程项目。参与前瞻系列活动、在线直播互动,不仅可以与上万名开发者们一起交流,还有机会赢取直播专属好礼,与技术大咖连麦。

门票限量大放送!今日起点击阅读原文报名「2020 AI开发者万人大会」,使用优惠码“AIP211”,即可免费获得价值299元的大会在线直播门票一张。限量100张,先到先得!快来动动手指,免费获取入会资格吧!

点击阅读原文,直达大会官网。

更多精彩推荐

☞一站式杀手级 AI 开发平台来袭!告别切换零散建模工具

北京四环堵车引发的智能交通大构想

☞拜托,别再问我什么是堆了!

北京四环堵车引发的智能交通大构想

你公司的虚拟机还闲着?基于Jenkins和Kubernetes的持续集成测试实践了解一下!

从 Web 1.0到Web 3.0:详析这些年互联网的发展及未来方向

你点的每个“在看”,我都认真当成了喜欢

<think> 首先,用户的问题是关于HALCON中如何为元组增加成员的方法。用户提供了几个引用,但这些引用似乎与元组操作无关。引用[1]和[2]是关于深度学习和分类的,引用[3]是关于矩阵操作的,引用[4]是关于形状模型的金字塔级别。用户指定这些引用仅供参考,不是真正需求,我应该参考用户上一次的问题和我的回答。 回顾用户上一次的问题:用户提到了系统级指令,包括LaTeX格式要求等,但没有直接的问题历史。这是对话的第一个消息,所以没有之前的互动。用户说:"上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答"。但在这个对话中,用户的上一条消息是系统指令,然后是这个引用消息。实际上,用户的查询是:"我想查找在Halcon中为元组增加成员的方法 请问Halcon中为元组增加成员的方法"。所以,这是我的第一次回应。 我应该专注于回答用户的核心问题:在HALCON中如何为元组增加成员。 现在,什么是HALCON?HALCON是一个机器视觉库。元组在HALCON中类似于列表或数组,用于存储多个值。 在HALCON中,元组操作是常见的。要添加成员到元组,我可以回忆或推断常见的方法。 从引用[3]中,有提到`get_value_matrix`,但这与矩阵相关,不是直接元组操作。引用中没有直接讨论元组增加成员的操作。 我应该基于我的知识回答。在HALCON中,元组是不可变的吗?在HALCON中,元组通常是动态的,你可以添加、移除元素。 常见的方法: - 在HALCON中,使用`[ ]`操作符或特定函数来操作元组。 例如: - 初始化元组:`Tuple := [1,2,3]` - 添加元素:可以使用`append`函数或直接连接元组。 在HALCON文档中,添加元素到元组可以用`tuple_concat`或直接赋值。 具体函数:HALCON有`tuple_insert`或类似函数?我记得有`tuple_gen_const` for generating, but for adding, it might be `tuple_concat` or direct indexing isn't supported since tuples are immutable in some contexts. 在HALCON中,元组是动态序列。你可以使用`tuple_concat`来连接元组,从而添加元素。 例如: - 如果你有一个元组`T1 := [1,2,3]`,你想添加4,你可以做`T2 := [T1, 4]` 这会创建一个新元组`[1,2,3,4]`。 类似地,使用`tuple_concat(T1, tuple([4]))`。 HALCON有特定的函数如`tuple_insert`,但标准方式是通过连接。 确认:在HALCON中,操作符`|`可以用于连接元组。 例如:`NewTuple := Tuple | [NewElement]` 或者`NewTuple := [Tuple, NewElement]` 是的。 函数如`tuple_insert`存在,但连接是直接的方式。 现在,用户的问题是为元组增加成员,意思是在元组中添加元素。 所以,我应该在回答中解释这个方法。 结构回答: - 清晰、逐步解释。 - 使用中文,因为指令要求使用中文回答。 - 添加引用?用户提供了引用,但引用不相关。我应该只参考如果适用。引用[3]提到`get_value_matrix`,但不直接相关。或许不添加引用,除非必要。 指令说:"回答中引用的段落末尾自然地添加引用标识",但如果没有引用自提供的内容,就不需要。 用户说引用仅供参考,所以可能不需要在我的回答中引用它们。 生成相关问题:指令要求"生成相关问题"。在系统级指令中说"生成相关问题",在用户可见层没有明确,但我应该包括。 在示例中,有"§§相关问题§§"部分。 所以,在回答后,添加相关问题。 确保LaTeX语法正确:用户提到数学表达式,但这个问题是关于编程的,可能没有数学内容。如果需要,使用$...$,但这里可能不需要。 系统指令说所有行内数学表达式必须用$...$,但在这个上下文中,可能没有数学。 回答结构: 1. 介绍如何为元组增加成员。 2. 给出示例代码(使用正确的语法)。 3. 解释注意事项或替代方法。 4. 生成相关问题。 关于HALCON元组操作: 在HALCON中,元组可以像这样操作: - 使用方括号创建和修改元组。 例如,添加元素:`NewTuple := [OldTuple, NewValue]` 或者使用`tuple_concat`函数。 具体函数:查找标准方法。 从HALCON文档回忆: - `tuple_concat`:连接两个元组。 - `tuple_insert`:在指定位置插入元素。 - 或者直接使用操作符。 在HALCON脚本中,添加元素到元组的常见方式是使用`[Tuple, Element]`。 例如: ```halcon Tuple := [1,2,3] // 创建一个元组 Tuple := [Tuple, 4] // 添加元素4,现在Tuple是[1,2,3,4] ``` 或者,如果你有多个元素,可以使用`tuple_concat(Tuple1, Tuple2)`。 对于添加单个元素,`[Tuple, Value]`是最简单的。 在代码块中显示。 现在,回答用户: - 开始回答:"在HALCON中,为元组增加成员可以通过连接元组的方式实现。" - 解释:"元组是不可变序列,因此添加元素实际上是创建一个新元组。" - 给出示例。 相关问题生成: 基于这个问题,"生成相关问题",如Halcon元组的其他操作、性能考虑等。 例如: 1. 如何移除元组的成员? 2. HALCON中的元组有哪些常用函数? 3. 元组操作在实际应用中的例子。 确保回答真实可靠。 </think> ### HALCON中为元组增加成员的方法 在HALCON中,元组(tuple)是一种基本的数据结构,用于存储一系列值(如数字、字符串等)。元组在HALCON中是**不可变的**,这意味着一旦创建就不能直接修改。因此,为元组增加一个新成员(元素)时,需要通过创建新元组的方式来实现。最常用的方法是使用**元组连接操作符**或**内置函数**。下面我将逐步解释这些方法,并提供示例代码。 #### 方法1: 使用方括号操作符直接连接 这是最简单和最常用的方式。您可以将现有元组与新元素拼接成一个新元组: - 语法:`NewTuple := [Tuple, NewElement]` - 解释:`Tuple` 是现有元组,`NewElement` 是要添加的新值或多个值(可以是单个值或另一个元组)。 - 示例代码: ```halcon * 创建初始元组 Tuple := [1, 2, 3] * 添加一个元素(如数字4) NewTuple := [Tuple, 4] * 现在NewTuple的值是[1,2,3,4] ``` 如果要添加多个元素,可以一次性连接: ```halcon * 添加多个元素 NewTuple := [Tuple, 4, 'a', 'b'] // 结果:[1,2,3,4,'a','b'] ``` #### 方法2: 使用`tuple_concat`函数 如果您需要更精细的控制或处理大型元组,HALCON提供了内置函数`tuple_concat`: - 语法:`tuple_concat(Tuple1, Tuple2, NewTuple)` - 解释:此函数将两个元组连接成一个新元组。`Tuple1` 和 `Tuple2` 是输入元组,`NewTuple` 是输出结果。 - 示例代码: ```halcon * 创建两个元组 Tuple1 := [1, 2, 3] Tuple2 := [4, 5] * 连接元组 tuple_concat(Tuple1, Tuple2, NewTuple) * 现在NewTuple的值是[1,2,3,4,5] ``` 要添加单个元素,可以将新元素先封装成元组: ```halcon * 添加单个元素(如字符串"new") tuple_concat(Tuple1, ['new'], NewTuple) // 结果:[1,2,3,'new'] ``` #### 方法3: 使用`tuple_insert`函数(在特定位置插入) 如果您需要在元组的特定位置(如开头、中间或结尾)插入元素,可以使用`tuple_insert`函数: - 语法:`tuple_insert(Tuple, Index, Value, NewTuple)` - 解释:`Tuple` 是输入元组,`Index` 是要插入的位置索引(索引从0开始),`Value` 是要插入的新值,`NewTuple` 是输出结果。 - 示例代码: ```halcon * 创建初始元组 Tuple := [10, 20, 30] * 在索引1的位置插入元素99(即第二个元素之前) tuple_insert(Tuple, 1, 99, NewTuple) * 现在NewTuple的值是[10,99,20,30] ``` 要在结尾添加元素,设置索引为元组的长度(等同于方法1): ```halcon * 获取元组长度 Length := |Tuple| * 在结尾添加元素 tuple_insert(Tuple, Length, 99, NewTuple) // 结果等同于[Tuple, 99] ``` #### 注意事项 - **性能考虑**:由于元组是不可变的,每次添加元素都会创建新元组。这意味着在循环中频繁添加元素可能影响性能。如果处理大型数据集,建议先收集所有值到一个列表中(使用循环构建),再一次性创建元组。 - **元素类型**:HALCON元组支持混合类型(如数字、字符串、布尔值等),但添加时需确保类型兼容,避免运行时错误。 - **错误处理**:如果索引无效(如负数或超出范围),`tuple_insert` 会抛出错误。添加前可以用`tuple_length`检查长度。 - **替代数据结构**:如果经常需要动态添加元素,考虑使用其他数据结构如数组或列表(在HALCON中通常用元组模拟)。HALCON的矩阵(matrix)更适合数值操作,但添加元素方式类似(引用[3]提到矩阵操作,但元组更简单)[^3]。 #### 完整示例 以下是一个在HALCON脚本中添加元组成员的完整示例: ```halcon * 初始化元组 Tuple := ['apple', 'banana'] * 添加一个新元素到结尾(使用方括号操作符) NewTuple1 := [Tuple, 'cherry'] // 结果:['apple','banana','cherry'] * 使用tuple_insert在开头添加元素 tuple_insert(NewTuple1, 0, 'grape', NewTuple2) // 结果:['grape','apple','banana','cherry'] * 使用tuple_concat添加多个元素 Additional := ['orange', 'pear'] tuple_concat(NewTuple2, Additional, FinalTuple) // 结果:['grape','apple','banana','cherry','orange','pear'] ``` 通过这些方法,您可以灵活地在HALCON中管理元组数据。如需更多细节,参考HALCON官方文档的"Tuple Operators"部分。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

优快云资讯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值