2009-03-11 7 views
2

OCamlで深くネストされたリストを以下の文脈で操作することに問題があります。OCamlでリストを操作する

class foo (pIn:int)= 
object (self) 
    val p = pIn 
    val even = if (pIn mod 2) = 0 then true else (false) 
    method doIt = "doIt" 
    method isEven = even 
    method getP = p 
end;; 

let rec createListOfElements howMany = (
    Random.self_init(); 
    if howMany > 1 then ((new foo (Random.int 10))::(createListOfElements (howMany - 1))) 
    else ([(new foo (Random.int 10))]) );; 

let myList = createListOfElements 5;; 

let rec process1 param = 
    if param <= 10 then 
      let f = new foo param in   (
       if f#isEven then (myList <- List.append myList (createListOfElements f#getP)); 
       Printf.printf "%s\n" f#doIt; 
       process1 (param+1)         ) 
in process1 0;; 

エラーは「アンバインドされたインスタンス変数myList」です。どのように私はこの文脈でmylistに「List.appendはmyList(#GETP F createListOfElements)の結果を代入行くのです

おかげ


編集機能:?!

let myList = ref (createListOfElements 5);; 

let rec process1 param = 
    if param <= 10 then 
      let f = new foo param in   (
       if f#isEven then (myList <- !myList @ (createListOfElements f#getP)); 
       Printf.printf "%s\n" f#doIt; 
       process1 (param+1)         ) 
in process1 0;; 

答えて

1

ます関数のプログラミングでは永続データを使用するため、永続性を解除するために参照を使用する必要があります。myListの宣言にrefキーワードを使用してください。

let myList = ref (createListOfElements 5) 
リストの使用 !間接参照

ので、問題の行は、私はこのように、それはだとして、あなたは関数型プログラミングスタイルの精神にアキュムレータを使用することをお勧め

if f#isEven then 
    myList := !myList @ f#getP; 

次のようになります。

let rec process1 lst = function 
    | x when x <= 10 -> 
     let f = new foo x in 
     if f#isEven then 
      process1 (lst @ (createListOfElements f#getP)) (param+1) 
     else 
      process1 lst (param+1) 
    | _ -> lst 

編集:

私のコードをコンパイルせず、間違った記号を使用してthの値を変更していることに気付かなかったe参照。正しい記号は:=です。上記の私の変更を参照してください。私はあなたが参照を避けることを強くお勧めし、アキュムレータのルートを行くことを強く勧めます。

+0

元の投稿を編集しました。これをコンパイルすると同じエラーが返されます。あなたのコメントの2番目のコードボックスがcreateListOfElementsの呼び出しを逃していました(実際の関数はそれ以上のことをしますが、この名前/実装を単純化するために使用しています)。私は間違って何をしていますか? –