いくつかの簡単なコマンドを使用して、OCaml でインタラクティブな電卓を作成しています。ユーザーは、たとえば、独自の単純な関数 (数学関数) を定義できる必要があります。
let f(x) = x
let g(x) = 2*f(x)
現在、関数は関数型言語のように処理する必要があります。つまり、作成時の環境を記憶する必要があります。つまり、関数では、関数と変数であるその環境のクロージャを維持する必要があります。
のように形成されたタプルのリストに、現在定義されている関数を保持します(functions_present_at_the_time_of_creation, variables_present_at_the_time_of_creation, function_name, function_argument_names, function_formula)
。関数のリストに新しい関数を追加しようとすると (現在定義されておらず、何も上書きする必要がないと仮定しましょう)、関数のリストの最後まで繰り返し繰り返し、そこに追加したいと思います新しいタプル。
問題は、現在の関数リストのタイプが であると仮定して、(a*b*c*d*e) list
それ自体を含むタプルを最後に追加しようとすると、そのタイプが に変更されること((a*b*c*d*e) list*f*g*h*i) list
です。タプルにカプセル化されたリストをそれ自体に追加するにはどうすればよいですか?
この問題の回避策を見つけようとして書いた簡単な SSCCE を次に示します。
let rec add_to_end list list_copy dummy = match list with
| [] -> [(list_copy, dummy)]
| h::t -> h::(add_to_end t list_copy dummy)
let add list dummy = add_to_end list list dummy
これは、リストのコピーを使用してそれを実行しようとします。次の例は、コピーを使用せずに記述されています (もちろん、これらの例はどちらも機能しません)。
let rec add_to_end list dummy = match list with
| [] -> [(list, dummy)]
| h::t -> h::(add_to_end t dummy)
最初の例は、関数 add を使用しようとすると機能しませんが、たとえば次のように (インタープリターで) 実行すると機能します。
let l = [];;
let l = add_to_end l l 1;;
let l = add_to_end l l 2;;
let l = add_to_end l l 3;;
その後、正常に動作します。デザインの変更も考えているかもしれませんが、どんな提案でも大歓迎です。
編集:上記のコマンドの出力は次のとおりです。
# let l = [];;
val l : 'a list = []
# let l = add_to_end l l 1;;
val l : ('a list * int) list = [([], 1)]
# let l = add_to_end l l 2;;
val l : (('a list * int) list * int) list = [([], 1); ([([], 1)], 2)]
# let l = add_to_end l l 3;;
val l : ((('a list * int) list * int) list * int) list =
[([], 1); ([([], 1)], 2); ([([], 1); ([([], 1)], 2)], 3)]