Zig 内存分配器接口中的重映射函数应该“尝试扩展或缩小内存,以允许重定位”。特别是,它提到...
返回值
null
表示调整大小相当于分配新内存、从旧内存复制字节,然后释放旧内存。在这种情况下,调用者执行复制会更有效率。
我不明白为什么说执行复制更有效率。如果我想复制一些内存块,我必须分配一些新内存,复制字节并(最终)释放旧块。那么我获得了什么效率?
我唯一能想到的是,如果我已经有一个已分配的内存块,我可以重用它进行复制,在这种情况下我可以避免分配步骤。
Zig 内存分配器接口中的重映射函数应该“尝试扩展或缩小内存,以允许重定位”。特别是,它提到...
返回值
null
表示调整大小相当于分配新内存、从旧内存复制字节,然后释放旧内存。在这种情况下,调用者执行复制会更有效率。
我不明白为什么说执行复制更有效率。如果我想复制一些内存块,我必须分配一些新内存,复制字节并(最终)释放旧块。那么我获得了什么效率?
我唯一能想到的是,如果我已经有一个已分配的内存块,我可以重用它进行复制,在这种情况下我可以避免分配步骤。
考虑以下将列表中的每个元素加 1 的函数。
f : {{x + 1} each x}
f[(1;2;3)]
2 3 4
但是,以下函数不起作用——我假设incr
后一个表达式中的标识符未绑定。
f : {incr : 1; {x + incr} each x}
f[(1;2;3)]
'incr
[3] f@:{x + incr}
我如何在 kdb/q 中表达类似以下内容?
let f lst =
let incr = 1 in
List.map (fun x -> x + incr) lst
我试图理解haskell-skiplist 的内部代码。
作者定义了以下代数数据类型和一些相关函数——其细节并不重要。
data Node k v
= Node { nKey :: k
, nValue :: v
, nSibling :: Node k v
, nChild :: Node k v }
| Head { nSibling :: Node k v
, nChild :: Node k v }
| Nil
nodeLTKey :: forall k v. Ord k => Node k v -> k -> Bool
nodeEQKey :: forall k v. Eq k => Node k v -> k -> Bool
sibling :: forall k v. Node k v -> Node k v
稍后在insert
第 113 行附近的函数中,他们定义了一个类型为 的辅助函数Node k v -> (Node k v, Int)
。我把我困惑的部分摘录在下面。
go Nil = (Nil, wins)
go n
| nodeLTKey sN k = (n {nSibling = fst $ go sN}, -1)
| nodeEQKey sN k = (n {nSibling = sN {nValue = v}}, -1)
-- how can they update the inner record?
where
sN = sibling n
-- How can the compiler be sure that sN is a Node and not Head / Nil?
该sibling
函数返回 aNode k v
并且只有 a 的可能变体之一Node k v
实际上具有名为 的字段nValue
。我不明白第二个后卫如何确定sN
将有一个nValue
字段 - 即,sN
将是这种Node
情况而不是Head
/ Nil
。