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的两倍。
编辑:也许我需要澄清一下 连接如letat = lhs ^ rhs不是变异操作。 lhs将与原来的相同,并且rhs将与它相同。 concatted可能会或可能不会指向与lhs相同的内存段(只是具有更大的长度)。我所说的复制是一种“幕后”操作。从客户的角度来看,所有对象的行为就像它们是不可变的一样,构造lhs ^ rhs需要摊销O(| rhs |)时间(在这种意义上分摊,如果我们通过重复连接右边的数字来继续构建更长的切片,那么数字内部重新分配很小。) 编辑2:对不起,我想象连接的行为类似于D追加。 D不这样做是因为它们也允许切片可变数据,但在OCaml中,事情默认为不可变,所以这不是问题(至少,不比D列表更多)。答案 0 :(得分:0)
我认为你不明白列表是什么。你似乎认为列表就像一个c ++向量(我不知道D的切片,但是我发现它看起来像c ++向量)但有更多限制。
不是!列表是不可变,持久性并且提供常量时间缺点(::),并且使用数组无法实现此目的(即使使用你称之为切片的智能阵列。
您可以使用列表但不能使用数组的示例:
let l = [1; 2; 3; 4; 5]
let a = 0 :: l
let b = 1 :: l
最后两行是常量时间(无论l
的大小)并添加常量空间。