5

私はocamlに困っています。

カウンターを呼び出すたびにカウンターをインクリメントし、vargen文字列をカウンター番号と連結して、この新しい文字列を返す関数を作成したいと思います。

私が成功せずにしたことは次のとおりです。

let (counter : int ref) = ref 0;;
let (vargen : string) = "_t";;
let tmp = incr counter;ref (vargen ^ string_of_int !counter);;
Printf.printf "%s\n" !tmp;;
Printf.printf "%s\n" !tmp;;
Printf.printf "%s\n" !tmp;;
Printf.printf "%s\n" !tmp;;

しかし、私の出力は常に次のとおりです。

_t1
_t1
_t1
_t1

そして、私の出力はどうあるべきか:

    _t0
    _t1
    _t2
    _t3

私の問題を解決するためのアイデアはありますか?

みんなありがとう。

4

4 に答える 4

8

を記述するlet tmp = ref fooと、式fooが 1 回評価され、参照に格納される値が生成されます。参照にアクセスすると、元の式を再評価せずにこの値が返されます。

再評価を引き起こす方法は、代わりに関数を使用することです: 関数を書く場合(fun () -> foo)、これは値です: そのまま返され、関数に渡され、参照に格納されます。この値に引数を適用するたびに、式fooが評価されます。

クレメントの解決策は良いです。の考え方

let counter =
  let count = ref (-1) in
  fun () -> incr count; !count

参照は一度割り当てられますが、関数fun () -> incr count; !countが呼び出されるたびにインクリメントされます。関数に対してローカルな参照を持つことで、グローバル変数の落とし穴を回避できます。関数の「静的変数」と考えることができますが、counterそれは OCaml のスコープと評価規則の自然な結果であり、追加の関数固有の概念ではありません。

vargen呼び出されるたびに新しい独立したカウンターを作成する、さらに一般的なジェネレーターを作成することもできます。

let make_vargen prefix =
   let count = ref (-1) in
   fun () ->
     incr count;
     prefix ^ string_of_int !count

let fresh_t = make_vargen "t"
let () = print_endline (fresh_t ())  (* t0 *)
let () = print_endline (fresh_t ())  (* t1 *)
let fresh_u = make_vargen "u"
let () = print_endline (fresh_u ())  (* u0 *)
let () = print_endline (fresh_t ())  (* t2 *)
let () = print_endline (fresh_u ())  (* u1 *)
于 2012-05-05T07:50:52.037 に答える
3

あなたが使うことができます

let tmp = 
  let counter = ref 0 in
  (fun () -> incr counter; vargen ^ (string_of_int !counter))

を使用して関数を呼び出し、tmp ()カウンターを0から開始する場合は、0を-1に変更します。

于 2012-05-05T06:47:42.310 に答える
3

は値なのでtmp、一度実行されます。tmp関数に変更すると、呼び出される たびにカウンターが増加します。

さらに、簡単にするためstringに代わりに返すことができます:string ref

let counter: int ref = ref (-1);;
let vargen: string = "_t";;

// tmp now is a function
let tmp() = incr counter; vargen ^ string_of_int !counter;;

Printf.printf "%s\n" (tmp());;
Printf.printf "%s\n" (tmp());;
Printf.printf "%s\n" (tmp());;
Printf.printf "%s\n" (tmp());;
于 2012-05-05T06:42:44.557 に答える