加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

为什么OCaml中没有函数头?

发布时间:2020-12-16 07:51:39 所属栏目:百科 来源:网络整理
导读:在某些编程语言中,尤其是在C语言中,存在具有函数声明的头文件.这些函数“标题”位于代码之前,并且在具有相互递归的情况下是必需的.当函数头放在头文件中时,它们还有助于链接多个C文件一起编译的情况. 我对C文件中函数头的理解是它们有助于编译,因为它们定义
在某些编程语言中,尤其是在C语言中,存在具有函数声明的头文件.这些函数“标题”位于代码之前,并且在具有相互递归的情况下是必需的.当函数头放在头文件中时,它们还有助于链接多个C文件一起编译的情况.

我对C文件中函数头的理解是它们有助于编译,因为它们定义函数的类型,如果它在定义之前被调用.如果这是错误的,我会很高兴能够得到纠正和更好的信息,但这是我对它的理解.

所以我不明白,为什么其他语言 – 在这种情况下我单挑OCaml – 没有功能标题.在OCaml中,存在具有签名的模块,但是签名不允许您的函数实例化是相互递归的,即使给出了类型.为了在OCaml中进行相互递归,你需要使用“和”关键字,或者在另一个函数中本地定义一个函数(据我所知).

(* version 1 *)
let rec firstfun = function
  | 0 -> 1
  | x -> secondfun (x - 1)
and secondfun = function
  | 0 -> 1
  | x -> firstfun x

(* version 2 *)
let rec firstfun = function
  | 0 -> 1
  | x -> 
       let rec secondfun = function
         |0 -> 1
         | x -> firstfun x in
       secondfun (x - 1)

那么为什么会这样呢?它与多态性有关吗?有没有我不考虑的编译瓶颈?

解决方法

事实上,这不是关于标题,因为它们只是代码片段,使用预处理器复制粘贴到文件中.您的问题的根源是为什么我们需要外部值的完整定义,以便编译单元.例如,在C中,您可以自由使用任何外部函数,因为您提供了原型,而在旧版本的C中,您甚至不需要原型.

其工作原因是因为由C编译器生成的编译单元将包含未解析的符号(例如,在其他地方定义的函数或数据值),并且链接器的工作是将这些符号连接到它们各自的实现.

引擎盖下的OCaml对编译单元使用类似C的格式,实际上依赖于系统C链接器来生成可执行文件.因此,到目前为止没有实际或理论上的限制.

那么问题是什么?只要您可以提供一种外部符号,就可以轻松使用它.这是主要问题 – 如果两个编译单元(即文件)之间存在相互依赖(在类型级别上),则OCaml类型检查器无法推断出类型.这种限制主要是技术性的,因为类型检查器在编译单元级别上工作.这种限制的原因主要是历史性的,因为在编写OCaml编译器时,单独的编译是时髦的,因此决定在每个文件的基础上应用类型检查器.

总而言之,如果您能够提供OCaml类型检查器将接受的类型,那么您可以轻松地在编译单元之间引发相互递归.要从您的方式移动类型检查器,您可以使用不同的机制,例如Obj模块或外部定义.当然,在这种情况下,您要对类型定义的完整性负全部责任.基本上,与C语言相同.

由于您始终可以从编译器生成整个程序编译系统,它支持单独编译,只需连接一个大模块中的所有模块,替代解决方案是使用某种预处理器来收集所有定义,并将它们复制到一个文件(即一个编译单元)中,然后将编译器应用于它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读