Functional programming 如何使用LinkedList样式和就地修改实现堆栈?
在Functional programming 如何使用LinkedList样式和就地修改实现堆栈?,functional-programming,ocaml,Functional Programming,Ocaml,在Java中,很容易实现linkedlist风格的stack 我们只需创建一个内部类项,它有两个属性:值和下一个 那么我们总是第一个项目 然后,当按下按钮时,我们创建一个新的项目,让它的下一个点指向当前的第一个项目,然后让当前的第一个项目成为新的项目 可以对pop执行类似操作 但是我怎样才能在OCaml中做到这一点呢?尤其是当我们需要就地修改(可变)时 我之所以说mutable,是因为普通的pop只弹出值,而不是新堆栈。OCaml是一种多范式语言。使用可变数据一点也不困难。但是真正值得努力去学
Java
中,很容易实现linkedlist
风格的stack
我们只需创建一个内部类项
,它有两个属性:值
和下一个
那么我们总是第一个项目
然后,当按下按钮时,我们创建一个新的项目
,让它的下一个点指向当前的第一个项目
,然后让当前的第一个项目
成为新的项目
可以对pop
执行类似操作
但是我怎样才能在OCaml中做到这一点呢?尤其是当我们需要就地修改
(可变
)时
我之所以说mutable
,是因为普通的pop
只弹出值,而不是新堆栈。OCaml是一种多范式语言。使用可变数据一点也不困难。但是真正值得努力去学会没有它(IMHO)。它的好处惊人地大,成本惊人地小
尽管如此,下面是一个可变堆栈类型的快速草图
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={mutable stack:'a list}
让new_stack()={stack=[]}
let is_empty stack=stack.stack=[]
让push x stack=stack.stack raise未找到
|x::xs->stack.stackOCaml是一种多范式语言。使用可变数据一点也不困难。但是真正值得努力去学会没有它(IMHO)。它的好处惊人地大,成本惊人地小
尽管如此,下面是一个可变堆栈类型的快速草图
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={mutable stack:'a list}
让new_stack()={stack=[]}
let is_empty stack=stack.stack=[]
让push x stack=stack.stack raise未找到
|为了补充Jeffrey的优秀答案,我想在
在这种情况下,实现持久接口和
堆栈数据结构的可变接口,如可变
接口可以构建在持久接口之上
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
为了补充杰弗里出色的回答,我想在
在这种情况下,实现持久接口和
堆栈数据结构的可变接口,如可变
接口可以构建在持久接口之上
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
您能否详细说明堆栈数据结构需要哪些功能?此外,如果您希望能够替换堆栈中的元素,只需使用ref
类型的堆栈实现(如回答中所述)。您能否详细说明堆栈数据结构需要哪些功能?另外,如果您想替换堆栈中的元素,只需使用堆栈实现(如答案中所述)使用ref
类型。我只是添加了mutable
来表示某事是可变的?我只是添加了mutable
来表示某事是可变的?你不能这样将任何持久性数据结构转换为可变结构吗?@rgrinberg:与直接就地数据结构相比,这种情况并不常见,这样做时只有恒定的开销实现(以数组为例)。Jeffrey的代码在将一个完全正确的普适实现隐藏在易变性的面纱下方面是值得注意的,我明确地将这两个方面分开了?你不能用这种方式将任何持久数据结构转换为可变数据结构吗?@rgrinberg:与直接就地实现(以数组为例)相比,这样做的开销通常不是恒定的。Jeffrey的代码在将一个完全正确的普适实现隐藏在易变性的面纱下方面是值得注意的,我明确地将这两个方面分开了?