2013-04-01 40 views
1

我一直想弄清楚如何在OCaml中调用调整大小已经初始化的数组。然而,看起来虽然你可以编写一个函数来创建一个全新的数组,并且复制了旧数组的元素(和额外的插槽),但是该函数的输出不能分配给现有的数组。如何做到这一点?有没有一种简单的方法可以使用引用来做到这一点,如果不是没有?OCaml:动态数组?

这里有一个小例子:

 
let rec function_that_adds_to_array storage args ... = 
    (* let's say the function has a set of if-else constructs that controls what it does, and let's further say that one of the cases leads to: *) 
    let new_array = Array.make (Array.length storage) ("Null", ("Null", -2)) in 
    Array.blit collection 0 new_array 0 index; (* index is controlled by the function's recursion *) 
    Array.set new_array index (obj_name, obj_expr); 
    new_array) (* insert the macro at tail *) 
... 
;; 


### main method ### 
let storage = Array.make 10 ((x : string), (a, b)) in 
... 
while true do 
... 
storage = function_that_adds_to_array storage args....; 
... 

在function_that_adds_to_array(...)末尾的打印语句确认一个新的数组返回,包含初始阵列的旧元素,然而,在主要方法,存储保持一致。这是因为OCaml元素的不变性吗?我以为阵列是可变的。我环顾四周,还有一些人提到黑客想让OCaml像Perl一样行事,但是,使用一个人的resize黑客功能证明是徒劳的。任何方式我可以让存储成为一个新的阵列?它需要是一个可更新的元组集合(即(string,(x,y)))?

+2

如果你不是这样做的教育目的,我会建议看看电池的[dynarray](http://ocaml-batteries-team.github.com/batteries-included/hdoc2/BatDynArray.html) – rgrinberg

+0

我喜欢这个库,但是,它似乎没有包含在标准的OCaml发行版中(我把合适的开放和包含调用,但它告诉我它是一个未绑定的模块)。你能否为我提供一个获取和安装最新版BatDynArray及其所需库的好链接? – 9codeMan9

+3

安装[OPAM](http://opam.ocamlpro.com/doc/Quick_Install.html)。然后做'opam安装电池'。 “#require”电池;;“'接着打开电池;'' – rgrinberg

回答

4

在OCaml中,您不能指定变量,句点。数组没有特别的限制。但是,可以有一个绑定到引用的变量,该引用可以保存相同类型的不同值。这种结构在命令式语言中通常被称为“变量”。有不同大小的数组变量中x你如下可以写代码:

# let x = ref [| 0 |];; 
val x : int array ref = {contents = [|0|]} 
# Array.length x;; 
Error: This expression has type int array ref 
    but an expression was expected of type 'a array 
# Array.length !x;; 
- : int = 1 
# x := [| 2; 3 |];; 
- : unit =() 
# Array.length !x;; 
- : int = 2 

!运营商取消引用的参考,并:=运营商分配新值。

如果您是OCaml的新手,我将包括我的标准建议,您应该在决定重新创建您已知的命令式语言的模式之前调查使用不可变数据。如果你不是OCaml的新手,我为我的无礼道歉!

+1

命名很困难,特别是关于命名的命名!但我认为事物在FP世界历史上称为变量(在lambda微积分中)。 –

+0

完全同意你的看法。我不知道历史术语,谢谢! – didierc

+1

我同意了解有关不可变数据的更多信息。我对OCaml并不陌生,因为在过去的几个月里我一直在使用它,但是在将命令式编程转换为函数式编程之间遇到了一些困难。有些东西可以很好地转换,比如递归思考而不是标准循环,但是我发现访问命令式语言中更容易找到的某些功能比较容易,例如动态数组。 – 9codeMan9