我是一個ocaml noob。到目前爲止,使用普通的舊引用int或其他簡單的內置類型,對我來說,在所有方面都能像預期的那樣工作。我已經在refs是元組成員的元組上下文中使用它們。我可以更新裁判,取消引用他們,等鍵入的ref細胞?
# let e = 1, ref 1;;
val e : int * int ref = (1, {contents = 1})
# snd e := 2;;
- : unit =()
# e;;
- : int * int ref = (1, {contents = 2})
# !(snd e);;
- : int = 2
但只要我宣佈「裁判的」命名類型的一些其他聚合(甚至是內置簡單)型,東西一般不順利。我發現我不能再像以前那樣改變引用了,因爲他們沒有被聲明爲某種類型的「ref」類型。 !!和:=運算符失敗。
而語義似乎改變奇怪顯然不一致的方式。以下只是一個例子。爲什麼寫下面的第一個代碼塊是合法的,但在頂部循環(在下面)做類似的事情似乎是非法的?第一個塊被編譯器接受,並且其中我們可以匹配一個構造類型的ref並使用!訪問它的值。在線路13和14操作者這是所有循環隊列的範圍內,並使用從#使用在頂循環中的文件中加載:
type 'a element = 'a * 'a pointer
and 'a pointer = Pointer of 'a element ref;;
let next (_,n) = n;;
type 'a queue = 'a element option ref;;
let create() = None;;
(*passes compiler and behaves well*)
let enqueue queue x =
match !queue with
None ->
let rec elem = (x, Pointer (ref elem)) in
queue := Some elem;
| Some (_, Pointer last_newest_next) -> (*Insert between newest and oldest*)
let oldest = !last_newest_next in
let elem = (x, Pointer (ref oldest)) in
last_newest_next := elem;
queue := Some elem;;
在頂部環類似的努力(並且在此變化)失敗如下面,在這裏我也使用功能分解的元組,然後嘗試調用同一個運營商:
let rec elem = (1, Pointer (ref elem));;
let last = !(next elem);;
Characters 12-22:
let last = !(next elem);;
^^^^^^^^^^
Error: This expression has type int pointer
but an expression was expected of type 'a ref
是的,我使用-rectypes但我想嘗試這一次不使用遞歸縮寫類型,我一直堅持下去。注意頂部環以下的作品,但我不能肯定它相當於什麼,我真的想:
let last = next elem;;
val last : int pointer = (* ... *)
而且如果第一個代碼塊的行14更改爲不使用!運營商,它打破了。重寫(如下)會導致入隊函數通過編譯器,但行爲不端:
(*compiles but fails - que only ever holds one item*)
let enqueue queue x =
match !queue with
None ->
let rec elem = (x, Pointer (ref elem)) in
queue := Some elem;
| Some (_, Pointer last_newest_next) ->
let oldest = last_newest_next in
let elem = (x, Pointer oldest) in
last_newest_next := elem;
queue := Some elem;;
它必須是沒有!運算符(以及其他一些更改)時,倒數第二行實際上將elem指針指向自身,而不是更新指針(從匹配的已分解元素中的不同指針)指向elem。無論如何,我仍然不明白爲什麼語義看起來在類型化引用的頂級循環元組分解和ml文件中做同樣的操作之間不一致......如果這甚至是所有這些的原因。或者是從某種模式匹配中分解出來,與通過函數分解元組不同?!?
而且我用了一個出列函數來測試上述功能的行爲:
let dequeue queue =
match !queue with
None -> raise Not_found
| Some (_, Pointer oldest_ref) ->
let oldest = !oldest_ref in
let (x, Pointer next_ref) = oldest in
let next = !next_ref in
if next == oldest then
queue := None
else
oldest_ref := next;
x;;
我能明白爲什麼我可能要回避裁判細胞的功能性語言,但我需要知道如何使用它們當時勢在必行(無雙關語意)。
道歉的複雜的問題;感謝所有的答案,因爲他們幫助我的理解非常。 – paul