質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
OCaml

OCaml(オーキャムル)は、フランスのINRIAが開発した関数型言語MLの一種で、 最新の言語理論の成果が取り入れられているプログラミング言語です。

Q&A

解決済

1回答

722閲覧

ocaml実行について

kun_monimoni

総合スコア26

OCaml

OCaml(オーキャムル)は、フランスのINRIAが開発した関数型言語MLの一種で、 最新の言語理論の成果が取り入れられているプログラミング言語です。

0グッド

0クリップ

投稿2021/05/14 15:59

ocamlをターミナルから実行するにあたり、例えば、リストを反転させるといった再帰関数などで関数の呼び出し毎にどのようにリストが変化していくのかを見たいのですが、それを見る方法はありますか?
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

#traceディレクティブを使うと指定した関数に対する入力(引数)と出力(戻り値)を表示できます。

たとえば、上のチュートリアルの例を拝借すると、以下のように使えます。

ocaml

1# (* fib関数を定義する *);; 2# let rec fib x = if x <= 1 then 1 else fib (x - 1) + fib (x - 2);; 3val fib : int -> int = <fun> 4 5# (* fib関数に対するトレースをオンにする *) 6# #trace fib;; 7fib is now traced. 8 9# (* fib関数を適用する *) 10# fib 3;; 11fib <-- 3 12fib <-- 1 13fib --> 1 14fib <-- 2 15fib <-- 0 16fib --> 1 17fib <-- 1 18fib --> 1 19fib --> 2 20fib --> 3 21- : int = 3 22 23# (* fib関数に対するトレースをオフにする *) 24# #untrace fib;; 25fib is no longer traced.

fib <-- 3が入力で、fib --> 1が出力です。

この#traceはリストを反転させるような関数でももちろん使えますが、そのままだと多分うまくいきません。チュートリアルにも書かれているように、多相な関数(Polymorphic function)に対してトレースを使った場合、多相な値が<poly>のように表示されてしまい、実際の値を見ることができません。

たとえばリストを反転させるrev関数を以下のように定義したとします。

ocaml

1# let rec revAppend l1 l2 = 2 match l1 with 3 [] -> l2 4 | v :: l1' -> revAppend l1' (v :: l2);; 5val revAppend : 'a list -> 'a list -> 'a list = <fun> 6 7# let rev l = revAppend l [];; 8val rev : 'a list -> 'a list = <fun>

注:この定義は書籍『プログラミング in Ocaml』(五十嵐淳 著、技術評論社)から拝借しました。

これに対して#traceをかけても有益な情報は得られません。

ocaml

1# #trace revAppend;; 2revAppend is now traced. 3 4# rev [1; 2; 3];; 5revAppend <-- [<poly>; <poly>; <poly>] 6revAppend --> <fun> 7revAppend* <-- [] 8revAppend <-- [<poly>; <poly>] 9revAppend --> <fun> 10revAppend* <-- [<poly>] 11revAppend <-- [<poly>] 12revAppend --> <fun> 13revAppend* <-- [<poly>; <poly>] 14revAppend <-- [] 15revAppend --> <fun> 16revAppend* <-- [<poly>; <poly>; <poly>] 17revAppend* --> [<poly>; <poly>; <poly>] 18revAppend* --> [<poly>; <poly>; <poly>] 19revAppend* --> [<poly>; <poly>; <poly>] 20revAppend* --> [<poly>; <poly>; <poly>] 21- : int list = [3; 2; 1]

チュートリアルによると、これを回避する簡単な方法は引数に型制約を付けて単相な関数として定義することだそうです。以下のようにrevAppendの引数をそれぞれint list(整数のリスト)型に制限すれば実際の値を見ることができます。

ocaml

1# let rec revAppend (l1 : int list) (l2 : int list) = 2 match l1 with 3 [] -> l2 4 | v :: l1' -> revAppend l1' (v :: l2);; 5val revAppend : int list -> int list -> int list = <fun> 6 7# let rev l = revAppend l [];; 8val rev : int list -> int list = <fun> 9 10# rev [1; 2; 3];; 11revAppend <-- [1; 2; 3] 12revAppend --> <fun> 13revAppend* <-- [] 14revAppend <-- [2; 3] 15revAppend --> <fun> 16revAppend* <-- [1] 17revAppend <-- [3] 18revAppend --> <fun> 19revAppend* <-- [2; 1] 20revAppend <-- [] 21revAppend --> <fun> 22revAppend* <-- [3; 2; 1] 23revAppend* --> [3; 2; 1] 24revAppend* --> [3; 2; 1] 25revAppend* --> [3; 2; 1] 26revAppend* --> [3; 2; 1] 27- : int list = [3; 2; 1]

最後に、念のため補足しますと、トレースの最初の3行のところですが、

ocaml

1revAppend <-- [1; 2; 3] 2revAppend --> <fun> 3revAppend* <-- []

これは第1引数l1[1; 2; 3]で、第2引数l2[]であることを表しています。OCamlの関数はカリー化されており引数を1つだけとるため、このように表示されます。

投稿2021/05/15 13:27

編集2021/05/16 01:15
tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kun_monimoni

2021/05/16 13:43

ご回答ありがとうございます。 わかりやすく丁寧な説明でとてもありがたいです。 機会がありましたらまたよろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問