Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ocaml 为什么有必要使用“;rec";_Ocaml - Fatal编程技术网

Ocaml 为什么有必要使用“;rec";

Ocaml 为什么有必要使用“;rec";,ocaml,Ocaml,我定义了以下函数,它计算两个数的最大公约数 let rec gcd n m = if m = 0 then n else gcd m (n mod m);; 如果没有关键字rec,它将无法工作 我很好奇,为什么需要有rec 在作用域中没有其他名为gcd的函数,因此编译器必须调用什么就很清楚了 即使作用域中有另一个函数gcd,编译器也可以尝试按某种顺序进行匹配,并查看适合的函数,如Haskell中的函数 你能举个例子说明为什么这很有用吗?大多数函数都是非递归函数,因此,默认情况下,函数名在函数体

我定义了以下函数,它计算两个数的最大公约数

let rec gcd n m = if m = 0 then n else gcd m (n mod m);;
如果没有关键字
rec
,它将无法工作

我很好奇,为什么需要有
rec

在作用域中没有其他名为
gcd
的函数,因此编译器必须调用什么就很清楚了

即使作用域中有另一个函数
gcd
,编译器也可以尝试按某种顺序进行匹配,并查看适合的函数,如Haskell中的函数


你能举个例子说明为什么这很有用吗?

大多数函数都是非递归函数,因此,默认情况下,函数名在函数体中不可见是合理的。这也有助于重新定义函数,假设您有模块
User
name
函数,并且希望在新模块中重新定义它:

module User = struct 
   type t = {name : string}
   let name t = t.name
end

module RespectedUser = struct 
  include User
  let name t = "Mr. " ^ name user
end

如果
name
name(在本例中,函数名的选择是多么糟糕)在主体中可见,那么实现
name
函数就会困难得多。它会更多地阻碍我们,然后才是真正需要的。在Haskell中编程时,当您意外地使函数递归时,这始终是我的一个问题,尽管您只是想重载现有函数。

大多数函数都是非递归的,因此,默认情况下,函数名在其主体中不可见是合理的。这也有助于重新定义函数,假设您有模块
User
name
函数,并且希望在新模块中重新定义它:

module User = struct 
   type t = {name : string}
   let name t = t.name
end

module RespectedUser = struct 
  include User
  let name t = "Mr. " ^ name user
end

如果
name
name(在本例中,函数名的选择是多么糟糕)在主体中可见,那么实现
name
函数就会困难得多。它会更多地阻碍我们,然后才是真正需要的。在Haskell中编程时,当您意外地使函数递归时,这对我来说总是一个问题,尽管您只是想重载现有函数。

是否
rec
表示您希望它执行TCO?如果是这种情况,就像Scala的递归注释一样,如果不能优化递归,它会警告您。@Carcigenicate:No,
rec
对于任何递归函数定义都是必需的。是否可能是的一半重复?它是关于F#,但显然它们的根是相似的。
rec
的可能重复是否表示您希望它执行TCO?如果是这种情况,就像Scala的递归注释一样,如果不能优化递归,它会警告您。@Carcigenicate:No,
rec
对于任何递归函数定义都是必需的。是否可能是的一半重复?它是关于F#,但显然它们的根是相似的。Haskell和OCaml的可能副本都不支持重载。你用
name
的定义替换了旧的定义。我的意思是覆盖(通常混淆这两个词)。OCaml支持方法重载,因为方法具有后期绑定。重载是指如果您有两个同名的函数,但参数的数量或类型不同,并且编译器根据您使用的参数调用正确的函数。重写是指子类定义的方法与超类型具有相同的签名,并且在运行时根据接收方的类型选择正确的版本。OCaml不支持前者。它确实支持后者。你所做的都不是。不,只是检查了术语,我是对的。这叫做重载。使用新方法重载作用域中的现有名称时。最重要的是当你将同一个变量反弹到新名称时。(前面的答案是对我的第二条评论的评论,它与你的评论同时出现)。好吧,我们从不同的语言中挑选术语,到目前为止术语还没有固定下来。我对重载有不同的定义。也许,重新绑定名称会更好。你同意吗?Haskell和OCaml都不支持重载。你用
name
的定义替换了旧的定义。我的意思是覆盖(通常混淆这两个词)。OCaml支持方法重载,因为方法具有后期绑定。重载是指如果您有两个同名的函数,但参数的数量或类型不同,并且编译器根据您使用的参数调用正确的函数。重写是指子类定义的方法与超类型具有相同的签名,并且在运行时根据接收方的类型选择正确的版本。OCaml不支持前者。它确实支持后者。你所做的都不是。不,只是检查了术语,我是对的。这叫做重载。使用新方法重载作用域中的现有名称时。最重要的是当你将同一个变量反弹到新名称时。(前面的答案是对我的第二条评论的评论,它与你的评论同时出现)。好吧,我们从不同的语言中挑选术语,到目前为止术语还没有固定下来。我对重载有不同的定义。也许,重新绑定名称会更好。你同意吗?