- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
书中Real World OCaml ,作者阐述了为什么 OCaml 使用 let rec
来定义递归函数。
OCaml distinguishes between nonrecursive definitions (using let) and recursive definitions (using let rec) largely for technical reasons: the type-inference algorithm needs to know when a set of function definitions are mutually recursive, and for reasons that don't apply to a pure language like Haskell, these have to be marked explicitly by the programmer.
强制执行 let rec
而纯函数式语言则不执行的技术原因是什么?
最佳答案
当您定义函数定义的语义时,作为语言设计者,您可以选择:要么使函数的名称在其自身范围内可见,要么不可见。两种选择都是完全合法的,例如 C 系列语言远非功能性的,但仍然具有在其范围内可见的定义名称(这也扩展到 C 中的所有定义,使得 int x = x + 1
合法)。 OCaml 语言决定给我们额外的灵 active ,让我们自己做出选择。这真的很棒。他们决定默认使其不可见,这是一个相当不错的解决方案,因为我们编写的大多数函数都是非递归的。
关于引用,它并不真正对应于函数定义 - rec
最常见的用法关键词。它主要是关于“为什么函数定义的范围没有扩展到模块的主体”。这是一个完全不同的问题。经过一番研究,我发现了一个非常similar question ,有 answer ,这可能会让你满意,引用它:
So, given that the type checker needs to know about which sets ofdefinitions are mutually recursive, what can it do? One possibility isto simply do a dependency analysis on all the definitions in a scope,and reorder them into the smallest possible groups. Haskell actuallydoes this, but in languages like F# (and OCaml and SML) which haveunrestricted side-effects, this is a bad idea because it might reorderthe side-effects too. So instead it asks the user to explicitly markwhich definitions are mutually recursive, and thus by extension wheregeneralization should occur.
即使没有任何重新排序,使用任意非纯表达式,可能会出现在函数定义中(定义的副作用,而不是评估),也不可能构建依赖关系图。考虑从文件中解码并执行函数。
总而言之,let rec
有两种用法构造,一是创建一个自递归函数,比如
let rec seq acc = function
| 0 -> acc
| n -> seq (acc+1) (n-1)
另一种是定义相互递归函数:
let rec odd n =
if n = 0 then true
else if n = 1 then false else even (n - 1)
and even n =
if n = 0 then false
else if n = 1 then true else odd (n - 1)
在第一种情况下,没有技术原因坚持使用一个或另一个解决方案。这只是一个品味问题。
第二种情况比较困难。推断类型时,您需要将所有函数定义拆分为由相互依赖的定义组成的簇,以缩小类型环境。在 OCaml 中,它更难实现,因为您需要考虑副作用。 (或者您可以继续而不将其拆分为主要组件,但这将导致另一个问题 - 您的类型系统将受到更多限制,即,将不允许更多有效的程序)。
但是,重新审视最初的问题和 RWO 的引用,我仍然非常确定添加 rec
没有技术原因。旗帜。考虑一下,SML 也有同样的问题,但仍然有 rec
默认启用。 有技术原因,let ... and ...
用于定义一组相互递归函数的语法。在 SML 中,此语法不需要我们输入 rec
OCaml 中的 flag 确实如此,从而为我们提供了更大的灵 active ,例如能够使用 let x = y and y = x
交换到值。表达。
关于haskell - 非纯函数式语言 OCaml 出现 'let rec' 的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28796904/
我正在尝试以更命令的方式表达一组链式调用。例如,图像我们有一个函数,它接受一个列表和一个元素,并将该元素附加到列表的末尾: 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 ->
我是一名优秀的程序员,十分优秀!