我正在使用stack
在OCaml
中实施array
。
我希望它接受任何类型。这是我实施的一部分,我的问题也是关于它。
type 'a stack = {mutable storage : 'a array; mutable n : int};;
let create () = {storage = Array.make 2 0; n = -1};;
所以,上面,当我定义我的堆栈类型时,它很好。 storage
是'a array
,这是一个接受任何类型的数组。
但是当我实现create
函数时,我遇到了问题。如何初始化'a array
?我不能,对吧?当我创建它时,我必须给它一个初始值,对吗?
那么如何使用具有多态性的数组创建堆栈?
答案 0 :(得分:2)
为什么要在OCaml中使用数组实现堆栈?这没有任何意义,这不是C ++或Java。不可变堆栈:
type 'a stack = Empty | Stack of 'a * 'a stack
let pop = function
| [] -> raise (Invalid_argument "empty stack")
| x :: s -> x, s
let push x s = x :: s
let is_empty s = (s = Empty)
可变堆栈:
type 'a stack = 'a list ref
let create () = ref []
let pop s =
match !s with
| [] -> raise (Invalid_argument "empty stack")
| x :: xs -> s := xs ; x
let push x s = (s := x :: !s)
let is_empty s = (!s = [])
P.S。在你声称数组以某种方式变得更快之前,你应该进行测试。
答案 1 :(得分:1)
你可以懒惰地分配数组:
type 'a stack = {mutable storage : 'a array option; mutable n : int}
let create () = {storage = None; n = -1}
然后,您的推送功能将检查堆栈是否已初始化并创建不是。
的数组但是,更一般地说,我认为你最好用'a list ref来定义你的堆栈。或者甚至更好,使用不可变堆栈,即列表。
答案 2 :(得分:1)
您的storage
字段是可变的,因此您可以在不同的时间放置不同的数组。因此,您可以使用一个完全多态的空数组进行初始化(如空列表)。
另一种方法是为storage
字段使用选项类型,并在第一次推送操作时创建数组。
我有时会在生产代码中遇到此类问题。我通常最终使用选项类型。
(更好的方法是使用堆栈列表。除非您需要访问除顶部之外的元素,否则该阵列只会造成麻烦并且不会带来任何好处。)
<强>更新强>
这是一个函数,它返回一个比提供的数组大两倍的数组。为了灵活性,额外的元素不能保证具有任何特定的值(尽管实际上它们只是原始数组的第0个元素的副本)。
let double array =
let len = Array.length array in
if len = 0 then array (* 2 * 0 = 0 *)
else
Array.init
(2 * len)
(fun x -> if x < len then array.(x) else array.(0))