【问题标题】:Optional argument cannot be erased?可选参数不能被删除?
【发布时间】:2010-12-12 15:21:31
【问题描述】:

我想要一个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.

tutorial 表示这意味着我正在尝试创建一个没有非可选参数的函数。但是上面的函数显然需要非可选参数。

我可能只是在做一些非常愚蠢的事情,但是什么?

【问题讨论】:

标签: ocaml compiler-warnings optional-arguments


【解决方案1】:

是的,你的非可选参数不能是最后一个,因为由于 OCaml 支持部分应用程序,缺少最后一个可选参数的函数看起来就像一个仍在寻找可选参数的部分应用函数。它告诉你不打算提供可选参数的唯一方法是它看到你在它之后提供了一个参数。

如果你必须把它放在最后,你可以在它后面加上一个虚拟的unit 参数:

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

但在这种情况下,是的,改变顺序会更好。

【讨论】:

  • 所以应用函数也需要哑()参数。
【解决方案2】:

你需要一个非可选参数可选参数之后。 只需更改函数参数的顺序:

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

【讨论】:

  • 非常感谢。那个会让我大跌眼镜的。我习惯于像 Python 和 C++ 一样将可选参数放在最后。 :-(
【解决方案3】:

之前的解决方案可以编译,但不会给出预期的结果。函数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.]

...等于函数rev_list from the List module:

# 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.]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    相关资源
    最近更新 更多