了解Ada这个不同时代的编程语言

举报
码乐 发表于 2025/07/25 06:33:44 2025/07/25
【摘要】 1 简介Ada 是 1980 年代初期由美国国防部推动开发的一种编程语言,其主要目标是提高大规模、长期维护项目的安全性、可靠性和可维护性。虽然 Go(Golang)是在 2009 年发布的,目标不同(强调简洁、并发和工程效率),但许多 Go 的优秀特性,其实可以从 Ada 中看到早期的“影子”或思想来源。这里从多个维度分析 Ada 的一些先进设计理念,以及这些理念如何在 Golang 中被...

1 简介

Ada 是 1980 年代初期由美国国防部推动开发的一种编程语言,其主要目标是提高大规模、长期维护项目的安全性、可靠性和可维护性。

虽然 Go(Golang)是在 2009 年发布的,目标不同(强调简洁、并发和工程效率),但许多 Go 的优秀特性,其实可以从 Ada 中看到早期的“影子”或思想来源。

这里从多个维度分析 Ada 的一些先进设计理念,以及这些理念如何在 Golang 中被借鉴、继承或重新诠释。

2 Ada语言

它有大量极其复杂的函数式语言、形式定理证明器,以及…Ada,一种可追溯到 1983 年的随机政府语言。

此外,您还会注意到,在任何 Ada 文档中,在解释依赖类型的工作原理时,他们都没有觉得有必要提出集合论或 λ 立方体:P

这种高度形式化的学术 / 研究 / 娱乐语言与一种非常官僚主义的语言并置,后者的设计理念与 COBOL 的设计理念非常相似。

但是,如果函数式程序员 / 类型论的人来问关于 Ada 的依赖类型的问题,这是写一篇大文章来解释 Ada 中的依赖类型的动力。Ada说明设计人员是如何真正尝试实现特定目标的,而巧合的是,他们的解决方案符合依赖类型的正式定义。

请注意,我真的根本不了解函数式编程或类型论,所以我不能真正谈论太多,---- 我对 Ada 不熟练。

3 Ada 的依赖类型

首先,为了上下文,这里对我所说的内容进行了非常简化的总结,因为它是一个罕见的功能:依赖类型只是依赖于某些具体值的类型。

因此,例如,具有数组字段的结构体,其长度取决于结构体中的另一个字段,这是 Ada 依赖类型2 的主要应用之一。

我还需要谈谈 Ada 的一个设计理念,即避免动态分配,除非出于安全原因确实需要

因为它没有像 Rust3 那样的完全安全分配的借用检查器。关键问题是,当您使用一个调用堆栈同时存储返回地址和局部变量时,被调用函数无法向上返回其堆栈分配的变量之一的内容,因为被调用方需要能够弹出返回地址,并使堆栈指针精确地位于调用之前的位置。

相反,任何大于 register 的返回值都必须由调用者分配其堆栈槽,其大小为调用者所知。Ada 通过第二个非调用堆栈4 解决了这个问题,函数可以在该堆栈上分配编译时未知空间并向上返回该空间,而无需动态分配并保留堆栈提供的良好范围和自由词法释放。

在 Ada 中真正需要动态分配的唯一时间是当您与 C/C++/Fortran/COBOL5 互通时,或者如果您的聚合类型包含未知长度的对象,例如字符串数组,您必须动态分配所有字符串,

然后可以像往常一样处理指针数组(Ada 具有丰富的容器库,因此您很少需要考虑它all) 的 S Ban允许使用第二个堆栈而不是动态分配(即避免在其他地方需要指针,以便将未定义长度的对象封装在另一个对象中)是 Ada 依赖类型的一种样式的关键动机。

4. 强类型与类型建模(Type Modeling & Safety)

Ada 的特性(1983)
Ada 强调 类型的语义建模:不仅是“整数”,而是“米数”、“秒”、“角度”等带有含义的数值。

支持 强类型派生(Strong Typing / Type Derivation):

      type Meter is new Float;
      type Second is new Float;

– 即使它们都是 Float,也不能混用
编译器检查语义一致性,避免因类型误用导致的 bug。

  • Go 的类比

Go 虽然是静态类型语言,但强调的是“简洁”和“实用”,类型系统没有 Ada 那么强,但也具备一些类型安全的特性:

明确类型定义 type Celsius float64 等可避免误用。

接口类型(interface)则体现另一种“意图表达”。

Go 的 go vet 等工具有助于静态分析,这也是 Ada 的早期核心哲学。

启发:

Ada 的类型系统关注“意义建模”,Go 则以轻量级方式实现相似目标:通过显式类型、工具链确保语义正确。

4. 并发模型(Concurrency)

Ada 的特性
提供“任务(Tasks)”为语言级并发模型,1983 年就具备:

  task type Worker is
    entry Start;
  end Worker;

支持“Rendezvous”同步方式,表达安全同步点。

Go 的特性

Go 的并发模型建立在 goroutine + channel 机制上,强调 CSP(Communicating Sequential Processes)。

		go func() { ch <- result }()

✅ 启发:Ada 是最早将并发视为一等公民的语言之一,Go 沿用这一理念,但用更现代、简洁的语法实现了广泛普及。

5 安全与健壮性(Safety & Robustness)

Ada 的特性

提供运行时检查:数组越界、空指针、除零等。

“设计即为正确”的理念:通过类型、范围检查等将 bug 杜绝在编译时或早期运行时。

Go 的特性

没有泛化的运行时检查(如越界 panic 可能崩溃),但仍提供一些内建检查机制。

Go 的 philosophy 是“make it simple enough to be safe”,而不是像 Ada 那样构建复杂机制。

启发:两者都在语言级支持更高的代码安全,但方式不同,Ada 偏向保守/形式化,Go 偏向实用主义/自动化。

6 模块化与封装(Modularity)

Ada 的特性

强大的包(Package)机制:

明确分离接口(spec)与实现(body)

清晰的封装和信息隐藏。

Go 的特性

简单的包机制:每个文件夹为一个包。

无类,但支持通过组合、接口实现封装。

启发:Ada 提供了一种精确控制暴露和隐藏信息的方式,Go 虽然简单,但也借鉴了清晰分层和模块边界的思想。

7 编译器为中心(Compiler-Oriented Philosophy)

Ada

语言设计鼓励编译器尽可能在编译期捕捉错误,强调 编译器理解程序意图。

可用于形式验证(SPARK/Ada)。

Go

Go 的编译器极快,鼓励频繁构建、快速反馈。

静态工具链(如 go vet, go fmt, go mod, go generate)继承了“编译器驱动开发”的哲学。

启发:Ada 的理念是“聪明的编译器为聪明程序员服务”,Go 则是在工程效率层面践行这一思想。

8 小结:Ada 与 Go 的理念交集

  特性		 Ada(1983)   					Go(2009) 类比或演化
  类型建模  	强类型 + 类型语义  			简洁类型定义 + 明确接口  Go 的 type 定义受启发
  并发模型 		 Task + Rendezvous Goroutine + Channel  都是语言内建并发
  模块系统 		 Package 分 spec/body  包与接口组合   不同方式实现信息封装
  静态检查  	编译时/运行时严格检查 快速编译 + 工具支持 Go 用工具链实现一部分 Ada 的特性
  编译器哲学 	编译器理解程序员意图  编译器和工具链驱动开发 相似理念,不同实现风格

虽然 Go 和 Ada 分别代表了两个时代(高可靠 vs 高效率)的语言哲学,但它们都体现了一种 “让程序更安全、更清晰、更工程化” 的共通追求。

Go 没有直接继承 Ada 的语法或结构,但在设计理念上,“通过类型、并发模型和编译器工具提升程序正确性” 是两者的重要交集。

如果你感兴趣,我也可以进一步提供具体代码对比,展示 Ada 与 Go 在类型、并发、模块等方面的异同。

【版权声明】本文为华为云社区用户翻译文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容, 举报邮箱:cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。