gpt4 book ai didi

ocaml - 是否可以在 OCaml 中定义剩余参数?

转载 作者:行者123 更新时间:2023-12-03 22:53:43 25 4
gpt4 key购买 nike

相关线程在 reddit .

在racket中,我们可以用rest argument定义一个函数作为:

(define (avg . l)
(/ (apply + l) (length l)))

我们可以这样调用这个函数:

> (avg 1 2 3)
2

有很多方法可以解决 reddit 回复中提到的这个特定的 avg

但是如果我想做一些更复杂的事情,比如:

(define *memoize-tbl* (make-hasheq))

(define (bind fn . args)
(let ([res (apply fn args)])
(hash-set! *memoize-tbl*
(equal-hash-code (cons fn args))
res)
res))

(define (f1 loi i s)
(+
(length loi)
i
(string-length s)))

(bind f1 '(1 2 3) 8 "hi")

我们可以看到 bind 函数不关心 fn 有多少个参数,参数的类型可以是任何类型:整数、列表、字符串。

我想知道 OCaml 中是否有类似的语义?

最佳答案

ML 和 Haskell 并没有真正与 Lisp 的 &rest(或类 Lisp 语言的类似功能)相对应。撇开类型问题不谈,函数的定义方式意味着没有好的方法来定义函数的“剩余参数”。

使用“rest”参数的主要两个应用是可变参数函数和函数包装器。 Reddit 线程已经回答了如何执行可变参数函数(使用列表参数),所以我认为这是关于函数包装器的,这里的事情可能会变得有点棘手。

您遇到的根本问题是,对于不专门使用元组或列表参数的 ML 函数,实际上并不存在参数列表或元组的概念。例如函数

let d x y = abs (x - y)

等价于函数

let d x = (fun y -> abs (x - y))

换句话说,一个 (n+1) 元函数实际上是一个函数,当应用于单个参数时,会产生一个 n 元函数。例如,d 0 返回一个描述距 0 的距离的一元函数。

如果你想对参数元组进行操作,那么你需要这样指定它们:

let d (x, y) = abs (x - y)

然后您可以使用(例如)d(3, 5) 而不是 d 3 5 来调用它。请注意,优化的 OCaml 编译器通常应该为这两种情况生成相同的代码。

您可以很容易地从类型中分辨出来。第一个函数 (d x y) 的类型是

int -> int -> int

而第二个 (d(x, y)) 具有类型

int * int -> int

Arity 在前一种情况下变成了一个非常模糊的概念:我们有一个二元函数返回类型 int 的值还是一个一元函数返回 int -> int?编译器无法分辨,你必须看程序员的意图,所以你必须告诉包装器确切地包装哪些部分。

当你有元组形式的参数时,你可以很容易地定义内存,因为元组只是一个单一的参数。例如,让我们定义 Ackermann 函数,然后对其应用内存:

let rec ack = function
| (0, n) -> n + 1
| (m, 0) -> ack (m-1, 1)
| (m, n) -> ack (m-1, ack(m, n-1))

let memoize f =
let memo_table = Hashtbl.create 0 in
let f' x = try
Hashtbl.find memo_table x
with Not_found -> begin
let y = f x in Hashtbl.add memo_table x y; y
end in f'

let ack = memoize ack

请注意,这个简单示例实际上并未将记忆化应用于递归调用,而仅应用于顶级调用。不过思路应该还是很清晰的。

此外,如果转换涉及非平凡的多态行为,您可能需要一个仿函数而不是函数来表达转换。

通过一些样板,您还可以将其应用于 f x y 表示法。例如,如果您编写了 ack 来接受两个 int 参数而不是一对 int,那么您可以这样写:

let ack m n = memoize (fun (m, n) -> ack m n)

如果你真的雄心勃勃,你甚至可以编写一个 PPX 重写器将其编码为语法扩展点的一部分,这样你就可以编写如下内容:

let%memoize ack x y = ...

关于ocaml - 是否可以在 OCaml 中定义剩余参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35968221/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com