【发布时间】:2014-05-23 09:59:32
【问题描述】:
OCaml 是否有切片(例如不可变数据的 D 切片)?看起来它非常适合 OCaml 范例(您可以避免每次想要使用尾递归进行任何类型的处理时都必须不断地反转列表,因为您可以从两端访问/切片列表)。实施起来会不会很困难?
举个例子,如果 OCaml 列表表现得像切片,我可以说
let merge lhs rhs =
merge_helper lhs rhs []
let rec merge_helper lhs rhs res =
match lhs with
| [] -> res ^ rhs
| l_first :: l_rest ->
match rhs with
| [] -> res ^ lhs
| r_first :: r_rest ->
if l_first <= r_first then
merge_helper l_rest rhs (res ^ [l_first])
else
merge_helper lhs r_rest (res ^ [r_first])
其中 lhs ^ rhs 尝试通过将 rhs 复制到 lhs 旁边的空间(如果可用)来连接它们,否则将它们复制到内存中至少是 lhs 两倍大的新插槽中。
编辑:也许我需要澄清一下 诸如 let concatted = lhs ^ rhs 之类的连接不是变异操作。 lhs 将与以前相同,而 rhs 将与以前相同。 concatted 可能指向或不指向与 lhs 相同的内存段(只是长度更大)。我所说的复制是一种“幕后”操作。从客户端的角度来看,所有对象的行为都好像它们是不可变的,并且构造 lhs ^ rhs 需要摊销 O(|rhs|) 时间(摊销的意义在于,如果我们通过重复连接右侧的事物来继续构造更长的切片,则数字内部重新分配的数量很少)。
编辑 2:对不起,我想象连接的行为类似于 D 附加。 D 没有这样做,因为它们也允许可变数据切片,但在 OCaml 中默认为不可变,所以这不会是一个问题(至少,不会比 D 列表更多)。
【问题讨论】:
标签: functional-programming ocaml d slice