【发布时间】:2013-01-07 03:47:12
【问题描述】:
Dave Herman's recent talk in Rust 说他们从 C++ 借用了这个属性。我找不到有关该主题的任何内容。谁能解释一下单态是什么意思?
【问题讨论】:
Dave Herman's recent talk in Rust 说他们从 C++ 借用了这个属性。我找不到有关该主题的任何内容。谁能解释一下单态是什么意思?
【问题讨论】:
单态化意味着生成通用函数的特殊版本。如果我编写一个函数来提取任何对的第一个元素:
fn first<A, B>(pair: (A, B)) -> A {
let (a, b) = pair;
return a;
}
然后我调用这个函数两次:
first((1, 2));
first(("a", "b"));
编译器将生成两个版本的first(),一个专门用于整数对,一个专门用于字符串对。
这个名字来源于编程语言术语“多态”——意思是一个函数可以处理多种类型的数据。单态是从多态代码到单态代码的转换。
【讨论】:
dyn 或在 C++ 中使用虚拟方法来选择动态调度。相比之下,Java 对所有内容都使用动态调度,甚至包括泛型(即参数多态)。
不确定是否有人还在关注这个,但 Rust 文档确实提到了它如何通过这个过程实现无成本抽象。来自Performance of Code Using Generics:
您可能想知道是否存在运行时成本 使用泛型类型参数。好消息是 Rust 实现了 以这样一种方式使用泛型,使您的代码运行速度不会变慢 与具体类型相比,泛型类型。
Rust 通过执行代码的单态化来实现这一点 在编译时使用泛型。单态化是一个过程 通过填充具体将通用代码转换为特定代码 编译时使用的类型。
在这个过程中,编译器执行与我们使用的步骤相反的步骤 创建示例 10-5 中的泛型函数:编译器查看 所有调用通用代码并生成代码的地方 调用通用代码的具体类型。
让我们通过一个使用标准的示例来看看它是如何工作的 库的 Option 枚举:
let integer = Some(5); let float = Some(5.0);当 Rust 编译这段代码时,它会执行单态化。中 在该过程中,编译器读取已在 Option实例和标识两种Option:一种是i32 另一个是f64。因此,它扩展了 选项转换为 Option_i32 和 Option_f64,从而替换 泛型定义与具体定义。
代码的单态版本如下所示。这 通用选项被替换为由创建的特定定义 编译器:
// Filename: src/main.rs enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, } fn main() { let integer = Option_i32::Some(5); let float = Option_f64::Some(5.0); }因为 Rust 将泛型代码编译成指定类型的代码 在每种情况下,我们都无需为使用泛型支付运行时成本。当。。。的时候 代码运行,它的执行就像我们复制每个代码一样 手动定义。单态化的过程使得 Rust 的 泛型在运行时非常高效。
【讨论】:
对此不确定;你能链接到谈话吗?这可能是一句随意的话。
Herman 可能创造了一个类似模板专业化的术语,它从模板生成相互不相关(非多态或“单态”)的类型/对象,这是一个多态结构。
【讨论】:
Rust Book 中有一个很好的单态解释
单态化是通过填充编译时使用的具体类型将通用代码转换为特定代码的过程。
从书中的例子中,如果你用Some定义了变量:
let integer = Some(5); let float = Some(5.0);当 Rust 编译这段代码时,它会执行单态化。在那期间 过程中,编译器读取
Option<T>中已经使用的值 实例并识别两种Option<T>:一种是i32,另一种是i32是f64。因此,它将Option<T>的通用定义扩展为Option_i32和Option_f64,从而将通用定义替换为 具体的。代码的单态版本如下所示。通用的
Option<T>替换为编译器创建的具体定义:文件名:src/main.rs
enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, } fn main() { let integer = Option_i32::Some(5); let float = Option_f64::Some(5.0); }
【讨论】: