在Java
中,很容易实现linkedlist
样式的stack
。
我们只创建一个内部类Item
,它有两个属性:value
和next
。
然后我们总是第一项。
然后在push
时,我们创建一个新的Item
并让其下一个指向当前的first item
,然后让当前的first item
成为新的item
}。
可以与pop
类似。
但是我怎么能在OCaml中做到这一点?特别是当我们想要in place modification
(mutable
)?
我说mutable
因为正常pop
只会弹出值,而不是新堆栈。
答案 0 :(得分:4)
OCaml是一种多范式语言。使用可变数据并不困难。但是如果没有它(恕我直言),这是值得努力的。这个好处非常好,成本也非常低。
尽管如此,这里是一个可变堆栈类型的快速草图。
type 'a stack = { mutable stack: 'a list }
let new_stack () = { stack = [] }
let is_empty stack = stack.stack = []
let push x stack = stack.stack <- x :: stack.stack
let pop stack =
match stack.stack with
| [] -> raise Not_found
| x :: xs -> stack.stack <- xs; x
(您也可以从定义type 'a stack = 'a list ref
开始,但此版本显示了如何拥有自己的可变记录字段。)
答案 1 :(得分:2)
为了补充杰弗里的优秀答案,我想在此注意到 在这种情况下,很容易实现两者持久性接口和 Stack数据结构的可变接口,作为可变的 接口可以构建在持久接口之上。
module Impl = struct
type 'a t = 'a list
let empty = []
let is_empty = function [] -> true | _ -> false
let push x stack = x::stack
let pop = function
| [] -> raise Not_found
| x::xs -> (x,xs)
end
module PersistentStack : sig
type +'a t
val empty : 'a t
val is_empty : 'a t -> bool
val push : 'a -> 'a t -> 'a t
val pop : 'a t -> 'a * 'a t
end = struct
include Impl
end
module MutableStack : sig
type 'a t
val new_stack : unit -> 'a t
val is_empty : 'a t -> bool
val push : 'a -> 'a t -> unit
val pop : 'a t -> 'a
end = struct
type 'a t = 'a Impl.t ref
let new_stack () = ref Impl.empty
let is_empty stack = Impl.is_empty !stack
let push x stack = (stack := Impl.push x !stack)
let pop stack =
let (x, xs) = Impl.pop !stack in
stack := xs;
x
end