加入收藏 | 设为首页 | 会员中心 | 我要投稿 江门站长网 (https://www.0750zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 建站资源 > 经验 > 正文

编程的模型:Java, Go, Rust, Swift, D等

发布时间:2020-11-13 15:20:54 所属栏目:经验 来源:互联网
导读:单态化泛型的下一步是在编译器后端中进一步推进。就像我们可以复制带有泛型类型占位符的源代码模板一样,我们可以生成带有特定类型占位符的机器代码。然后我们就可以像链接器的一样工作,通过memcpy和一些补丁,很快就可以把这些模板标记出来! 其缺点是每个

单态化泛型的下一步是在编译器后端中进一步推进。就像我们可以复制带有泛型类型占位符的源代码模板一样,我们可以生成带有特定类型占位符的机器代码。然后我们就可以像链接器的一样工作,通过memcpy和一些补丁,很快就可以把这些模板标记出来! 其缺点是每个单态化的副本不能被优化器特别优化,然而因为没有重复优化,所以编译速度可以快很多。我们甚至可以把代码stamper做成一个小小的JIT,被包含在二进制文件中,并在运行时把单态化的副本标记出来,以避免二进制文件的膨胀。

其实我并不知道有哪种语言的泛型是这样工作的,这只是我在写作本文时的一个想法,作为这个分类法的自然延伸,这也正是我希望从中得到的东西! 我希望这篇文章能让你更清楚地了解不同语言中的泛型系统,以及如何对他们分类,并促进你的思考,也许我们可能会发现新的酷炫的编程语言的方向。

下一种类型的单态化泛型,是在类型检查之后,把代码生成的过程再推进一步。上文提到用C++可以像动态类型语言中的获取泛型库函数内的错误类型,这是因为模板参数中基本只有一种类型。所以这就意味着我们可以通过在我们的元级中增加类型系统来解决这个问题,并静态检查它们是否支持你使用的操作。这就是泛型在Rust中的工作方式,在语言层面来说也是Swift和Haskell中泛型的工作方式。

在Rust中,你需要在你的类型参数上声明 "trait bounds",其中trait就像其他语言中的接口一样,声明了类型提供的一系列函数。Rust编译器会检查你的泛型函数的主体是否能与任trait bounds的类型一起工作,也不允许你使用trait bounds没有声明的函数。这样Rust中泛型函数在实例化时,就永远不会在库函数得到编译器错误。编译器也只需要对每个泛型函数进行一次类型检查

还有一个类似的例子是Rust的过程宏,它将token流作为输入,输出token流,同时提供程序将token流转换为字符串或者从字符串转换为token流。这种方法的优点是token流可以保存源代码位置信息。使用宏就可以直接将用户写的代码以token的形式从输入粘贴到输出,如果用户的代码在宏输出中引起编译器错误,编译器输出的错误信息将正确地指向用户代码所在的文件、行和列,但如果宏生成了错误,那么错误信息将指向宏调用。例如如果在日志调用中使用了一个封装函数的宏,而在封装函数的实现中出错,编译器的错误将直接指向错误所在的你的代码,而非指向宏。

语法树宏

有些语言确实更进一步,提供了在宏中消费和产生抽象语法树(AST)类型的功能。这方面的例子包括模板Haskell、Nim macros、OCaml PPX和几乎所有的Lisps。

AST宏的问题是,你不希望用户学习一堆构造AST类型的函数。Lisp系列语言解决了这个问题,其语法和AST有非常直接的对应关系,但构造过程仍然会很繁琐。因此,我提到的所有语言都有某种形式的 "引用 "原语,你在语言中提供一个代码片段,它就会返回语法树。这些引用原语也提供方法来拼接语法树的值,就像字符串拼接一样。下面是模板Haskell中的一个例子。

Swift的泛型实现更加有趣,通过使用字典传递,同时把类型的大小以及如何移动、复制和释放它们放到函数指针表中,该表可以提供所有所需的信息,以统一的方式处理任何类型,而不需要装箱。这样一来,Swift就可以在没有单态化的情况下实现泛型,也不需要把所有的类型都使用统一的表达。虽然仍然存在所有动态查找成本,然而也节省了分配内存、内存和缓存不连贯的成本。Swift编译器能够在模块内和跨模块使用注解为@inlinable的函数进行单态化处理(monomorphize)和内联泛型,以避免这些成本,其使用启发式算法来估算代码会膨胀多少。

此功能还解释了Swift为何以允许在结构体中添加和重新排列字段的方式实现ABI稳定性,尽管它们出于性能原因提供@frozen属性以选择退出动态查找。

反射是非常强大的,可以完成很多不同的元编程任务,但有一点它不能做,那就是创建新的类型或编辑现有字段的类型信息。如果我们增加了这样的能力,并通过反射来实现,最终就会得到动态类型语言。在Python和Ruby这样的语言中,其超强的反射系统会带来惊人的元编程能力,并且使用其元编程能力的代码无处不在。

"但是Tristan,动态语言不是这样工作的,他们只是用哈希表来实现一切!"有人可能会这么说。好吧,哈希表只是一个用于实现可编辑的类型信息表的数据结构。而且,这只是某些像CPython这样的解释器的工作方式。如果你看一眼像V8这样的高性能JIT是如何实现的,它的做法就类似vtables和反射信息! V8的隐藏类(vtables和反射信息)和对象布局与你在Java虚拟机中看到的类似,只是对象能够在运行时改为新vtable。

(编辑:江门站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读