OCaml 标准库中的list
类型是不可变的,你不能用它做任何事情。将指向列表的指针放入可变单元格不会使列表本身可变。幸运的是,您可以实现可变列表,甚至可以遵循 lisp 数据表示,例如,
type ('a,'b) cell = {mutable car : 'a; mutable cdr : 'b}
类型系统会与你对抗:)
此外,您似乎混淆了指针和引用。在 OCaml 中,所有装箱类型(如列表、字符串、浮点数等)都表示为指针。立即类型(例如int
, char
)和数据构造函数(例如None
)My_constructor
表示为带标签的整数。(顺便说一句,所有现代 lisps 都使用相同的表示形式)。
引用只是标准库中定义的类型
type 'a ref = {mutable contents : 'a}
所以它是一个装箱类型,包含一个指向任意值的可变指针。因此,例如,您可以在其中放置一个列表,{contents = [1;2]}
它将包含一个指向不可变列表的指针。您可以将 to 更改contents
为指向不同的列表,但不能更改列表本身。同样,有不可变的,你不能把不可变的东西变成可变的。
另外,请注意 OCaml 将共享数据,例如
let common_tail = [3;4]
let head_one = 1 :: common_tail
let head_two = 0 :: common_tail
他们都将共享相同的尾巴,例如,
List.tl head_one == List.tl head_two
通常,这是很无辜的,因为人们在 OCaml 中不经常使用可变数据类型,但您实际上可以创建一个引用列表,它们也将被共享,例如,
let common_tail = [ref 3; ref 4]
let head_one = ref 1 :: common_tail
let head_two = ref 0 :: common_tail
如果你现在将设置cadr
为33
List.hd (List.tl head_two) := 33;;
它将影响两个列表
# head_one;;
- : int ref list = [{contents = 1}; {contents = 33}; {contents = 4}]
# head_two;;
- : int ref list = [{contents = 0}; {contents = 33}; {contents = 4}]