- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
相关线程在 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/
我正在尝试以更命令的方式表达一组链式调用。例如,图像我们有一个函数,它接受一个列表和一个元素,并将该元素附加到列表的末尾: let insert l e = l @ [e] 我想一次插入几个元素。
是否有一个完整的列表(或详尽的规则)可以给 OCaml 中的自定义中缀运算符提供可能的名称? 最佳答案 如 OCaml manual 中所述, 中缀运算符必须匹配正则表达式 [-=<>@^|&+*/$
我想开始使用 OCaml 编程。由于我是 Windows 用户,我知道最好使用 Netbeans 的 OCaml 插件。 我已经从以下链接下载了上述插件:http://ocamlplugin.loki
能够做到这一点以获得最大速度不是很重要吗? 编辑: 例如,Clojure 有 map ,它使用多个核心。 Harrop 博士写道(2011 年 1 月 9 日): 语言中添加的新功能,例如一流 OCa
我在 x86 机器上用字节码编译 OCaml 程序,然后将字节码传输到 ppc64 机器。假设 ppc64 机器有 ocamlrun(为 ppc64 编译),我能在 ppc64 架构上执行我的程序吗?
我创建了一个新模块,它只是名称很长的模块的较短别名: module M = ModuleWithLongName 我处于最终可执行文件的大小很重要的情况。上面的构造是由编译器合理处理的吗(即 M 实际
我在使用 ocaml 时遇到了麻烦。 我想创建一个函数,每次调用它时都会增加我的计数器,并将我的 vargen 字符串与计数器编号连接起来,然后返回这个新字符串。 我没有成功的做法是: let (co
我正在学习 OCaml,我对变量的不变性有点困惑。根据我正在阅读的书,变量是不可变的。到目前为止一切顺利,但为什么我可以这样做: let foo = 42 let foo = 4242 我错过了什么?
非尾递归组合函数可以这样写: let rec combinations l k = if k List.length l then [] else if k = 1 then List.ma
我有一段包含camlp4引用的代码。 let f_name = "my_func" > 运行此程序后 camlp4of ,它产生这个: Ast.StExp (_loc, (Ast.ExAp
如何在 OCaml 中模拟这个 Python 习语? if __name__=="__main__": main() 见 RosettaCode其他编程语言中的示例。 最佳答案 Ocaml 中没
我开始学习 Ocaml,使用 hickey book ,我被困在练习 3.4,第 9 部分 让 x x = x + 1 在 x 2 运算结果为3 ,但我不明白为什么? 最佳答案 当你写 let x x
Rust具有线性系统。有什么(好的)方法可以在 OCaml 中模拟这个吗?例如,当使用 ocaml-lua 时,我想确保仅当 Lua 处于特定状态(堆栈顶部的表等)时才调用某些函数。 编辑 :这是最近
在 OCaml?我知道非常酷的Bitstring图书馆,但是 虽然这将是在某些协议(protocol)中解析二进制数据的好方法, 它不支持异或或移位等按位运算。 我相信该库使用的底层数据结构是 只是
我们可以像这样构造一个无限列表: let rec endless = 1::endless 我认为它会吃掉所有的内存,但是当我在 utop 中尝试时,好像不是这样。 utop显示列表已构建: val
是否可以通过合并列表的元素而不是创建列表的列表来创建列表? 例子: List.combine ["A";"B"] ["C";"D"];; 我得到: [("A", "C"); ("B", "D")] 有
我想在 OCaml 中创建一个查找表。该表将有 7000 多个条目,在查找时(通过 int)返回一个字符串。用于此任务的适当数据结构是什么?表是否应该从基本代码中外部化,如果是这样,如何“包括”查找表
我正在评估 Ocaml 顶层中的一段非常简单的代码: let p5 () = print_int 5;; p5 ();; print_string "*************************
记录和元组之间是否有任何区别而不仅仅是句法差异? 有性能差异吗? 元组和记录的实现是否相同? 您是否有可以使用元组完成但不能使用记录完成的事情的示例(和 反之)? 最佳答案 模数语法它们几乎相同。主要
OCaml 中的 ` 运算符有什么作用? let int_of_meth = function | `GET -> 0 | `POST -> 1 | `PUT ->
我是一名优秀的程序员,十分优秀!