为什么 OCaml/F# 中的函数默认不是递归的? [英] Why are functions in OCaml/F# not recursive by default?

查看:20
本文介绍了为什么 OCaml/F# 中的函数默认不是递归的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么 F# 和 OCaml(可能还有其他语言)中的函数在默认情况下不是递归的?

Why is it that functions in F# and OCaml (and possibly other languages) are not by default recursive?

换句话说,为什么语言设计者认为在如下声明中显式输入 rec 是个好主意:

In other words, why did the language designers decide it was a good idea to explicitly make you type rec in a declaration like:

let rec foo ... = ...

默认情况下不给函数递归能力?为什么需要显式的 rec 构造?

and not give the function recursive capability by default? Why the need for an explicit rec construct?

推荐答案

原始 ML 的法国和英国后裔做出了不同的选择,他们的选择几十年来一直继承到现代变体.所以这只是遗留问题,但它确实影响了这些语言中的习语.

The French and British descendants of the original ML made different choices and their choices have been inherited through the decades to the modern variants. So this is just legacy but it does affect idioms in these languages.

在法语 CAML 语言系列(包括 OCaml)中,函数默认不是递归的.这种选择使得在这些语言中使用 let 取代函数(和变量)定义变得容易,因为您可以在新定义的主体中引用以前的定义.F# 从 OCaml 继承了这个语法.

Functions are not recursive by default in the French CAML family of languages (including OCaml). This choice makes it easy to supercede function (and variable) definitions using let in those languages because you can refer to the previous definition inside the body of a new definition. F# inherited this syntax from OCaml.

例如,在OCaml中计算序列的香农熵时取代函数p:

For example, superceding the function p when computing the Shannon entropy of a sequence in OCaml:

let shannon fold p =
  let p x = p x *. log(p x) /. log 2.0 in
  let p t x = t +. p x in
  -. fold p 0.0

注意高阶 shannon 函数的参数 p 如何被主体第一行中的另一个 p 取代,然后正文第二行中的另一个 p.

Note how the argument p to the higher-order shannon function is superceded by another p in the first line of the body and then another p in the second line of the body.

相反,ML 语言家族的英国 SML 分支采取了另一种选择,SML 的 fun 绑定函数默认是递归的.当大多数函数定义不需要访问其函数名称的先前绑定时,这会导致代码更简单.但是,被取代的函数使用不同的名称(f1f2 等),这会污染作用域并可能意外调用函数的错误版本".现在隐式递归 fun 绑定函数和非递归 val 绑定函数之间存在差异.

Conversely, the British SML branch of the ML family of languages took the other choice and SML's fun-bound functions are recursive by default. When most function definitions do not need access to previous bindings of their function name, this results in simpler code. However, superceded functions are made to use different names (f1, f2 etc.) which pollutes the scope and makes it possible to accidentally invoke the wrong "version" of a function. And there is now a discrepancy between implicitly-recursive fun-bound functions and non-recursive val-bound functions.

Haskell 可以通过将定义限制为纯来推断定义之间的依赖关系.这使得玩具样品看起来更简单,但在其他地方却付出了沉重的代价.

Haskell makes it possible to infer the dependencies between definitions by restricting them to be pure. This makes toy samples look simpler but comes at a grave cost elsewhere.

请注意,Ganesh 和 Eddie 给出的答案是红鲱鱼.他们解释了为什么不能将函数组放在一个巨大的 let rec ... and ... 中,因为它会影响类型变量何时被泛化.这与 rec 是 SML 中的默认值而不是 OCaml 中的默认值无关.

Note that the answers given by Ganesh and Eddie are red herrings. They explained why groups of functions cannot be placed inside a giant let rec ... and ... because it affects when type variables get generalized. This has nothing to do with rec being default in SML but not OCaml.

这篇关于为什么 OCaml/F# 中的函数默认不是递归的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆