【发布时间】:2016-09-21 21:58:16
【问题描述】:
代数数据类型 (ADT) 是由可能递归的单位、乘积和总和类型组成的类型。
考虑一下 Haskell 中的一个简单 ADT:
data Tree = Empty
| Leaf Int
| Node Tree Tree
或者 Rust 中的另一个例子:
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
Haskell(垃圾回收)和 Rust(非垃圾回收)实际上是如何在内存中表示这些的,它们应该如何表示?
我主要对更简单的非垃圾回收案例感兴趣,但如果非垃圾回收,解决方案必须对堆和堆栈都适用,例如 Rust。
LLVM 或 C/C++ 中的表示是我感兴趣的。
使用第二个例子,我可以想到两个选择:
选项 1,使用联合:
enum MCtor { CQ, CCC, CM, CW };
struct Message {
enum MCtor ctor;
union {
void*; /* Quit */
struct { int r; int g; int b; } /* ChangeColor */
struct { int x; int y; } /* Move */
struct { char* str; } /* Write */
};
};
选项 2,使用单独分配,void* 和(位)转换:
enum MCtor { CQ, CCC, CM, CW };
typedef struct { int r; int g; int b; } ChangeColor;
typedef struct { int x; int y; } Move;
typedef struct { char* str; } Write;
struct Message {
enum MCtor ctor;
void* data;
};
模式匹配只是switch 上msg -> ctor 的问题。
哪一个更可取,尤其是考虑到递归类型?
在我的脑海中,我猜第一个的局部性更好,它可以避免负载,虽然它可能会使用更多的内存......所以第二个选项有更好的内存占用但性能更差.. .?
【问题讨论】:
-
这可能会因为太宽泛而被关闭。您在问哪个实现细节是最好的,但是变量太多了。您的目标是什么机器架构(缓存对齐和填充肯定会发挥作用)?您是否尝试优化速度或内存使用?我希望它还取决于将存储什么样的东西。您的语言中的所有内容都表示为指针吗?
-
请注意,Rust 不 直接允许递归类型定义。如果是这样,结构的大小将是无限的。它要求您通过引用或堆分配的存储添加一个间接层。
-
没有语言 C/C++。不确定 C++ 是否允许匿名
struct/union成员。而且您的问题主要是基于意见的并且过于广泛(选择一个)。任何都是有效的关闭理由。 -
@Olaf 我读到他们确实不允许在 c++ 中使用。
-
@Centril:ADT 不是元组,但它是一个联合:它是 一个 empy、leaf 或 node,而不是“全部”。只有节点是元组。