13

の末尾再帰バージョンが欲しかったList.mapので、自分で作成しました。ここにあります:

let rec list_map f l ?(accum=[])=
  match l with
      head :: tail -> list_map f tail ~accum:(head :: accum)
    | [] -> accum;;

この関数をコンパイルするたびに、次のようになります。

File "main.ml", line 69, characters 29-31:
Warning X: this optional argument cannot be erased.

チュートリアルによると、これは、オプション以外の引数を使用せずに関数を作成しようとしていることを意味します。しかし、上記の関数は明らかにオプションではない引数を取ります。

私はおそらく本当にばかげたことをしているだけですが、何ですか?

4

3 に答える 3

20

ええ、オプション以外の引数を最後にすることはできません。OCamlは部分適用をサポートしているため、最後のオプション引数がない関数は、オプション引数を探している部分適用関数のように見えるからです。オプションの引数を指定するつもりがないことを示す唯一の方法は、その後に引数を指定したことを確認することです。

最後に持っている必要がある場合は、その後にダミーのunit引数を置くことができます。

let rec list_map f l ?(accum=[]) () =
  match l with
      head :: tail -> list_map f tail ~accum:(head :: accum) ()
    | [] -> accum;;

しかし、この場合は、順序を変更した方がよいでしょう。

于 2009-11-03T15:05:25.213 に答える
12

オプションの引数の後に非オプションの引数が必要です。関数の引数の順序を変更するだけです。

let rec list_map f ?(accum=[]) l=
  match l with
    head :: tail -> list_map f  ~accum:(head :: accum) tail
  | [] -> accum;;
于 2009-11-03T13:09:44.743 に答える
4

以前のソリューションはコンパイルされますが、期待される結果は得られません。関数fが引数に適用されることはありません。正しいコードは次のとおりです。

let rec list_map f ?(accum = []) l = match l with
    | head :: tail -> list_map f ~accum:(f head :: accum) tail
    | [] -> accum;;

推測されるタイプは次のとおりです。

val list_map : ('a -> 'b) -> ?accum:'b list -> 'a list -> 'b list = <fun>

...間違ったものとは対照的に:

val list_map : 'a -> ?accum:'b list -> 'b list -> 'b list = <fun>

結果リストが逆になっていることに注意してください。

# list_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [16.; 8.; 4.; 2.]

...そしてListモジュールの関数rev_listと同じです:

# List.rev_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [16.; 8.; 4.; 2.]

したがって、関数を次のように変更することをお勧めします。

let rec list_map f ?(accum = []) l = match l with
    | head :: tail -> list_map f ~accum:(f head :: accum) tail
    | [] -> List.rev accum;;

...これも(マニュアルによると)末尾再帰である必要があり、元の順序でリストを返します。

# list_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [2.; 4.; 8.; 16.]
于 2009-12-02T12:33:55.610 に答える