关键字在OCaml中的工作方式

时间:2018-09-30 08:41:27

标签: ocaml

我知道如何在OCaml中使用关键字in。我的问题是编译器按哪个顺序执行表达式。

例如,让我们采用以下代码:

let v = expr1 in expr2

编译器首先查看expr2,然后当v出现在expr2中时,它将v替换为expr1吗? 或者首先,它计算expr1,然后应用expr2

您可能想知道为什么我要问这个奇怪的问题。这是由于我不理解以下代码的工作原理:

let rec some_function = function 
   | [] -> () 
   | t::q when (*here put a condition*) -> some_function q
   | t::q -> (*some operations here*); some_function q
in 
let s = (*some list*)
some_function s 

此代码如何工作? 我的意思是,当我们有递归调用some_function q时,程序是否直接进入in块并应用其他递归调用some_function s

1 个答案:

答案 0 :(得分:6)

当程序显示let v = expr1 in expr2时,OCaml首先评估expr1,然后在其中expr2与该值关联的环境中开始评估v。是expr1的结果。

这种评估策略call-by-value并非唯一可行的方法,而是OCaml所采用的策略。

现在让我们考虑一下代码段:

let rec some_function = function ...
in
let s = (*some list*)
some_function s 

程序包含上面的代码段时,将执行以下步骤:

  • function ...被评估。此步骤很短,因为评估function ...块并不意味着会评估...内部的代码。相反,对function ...求值的结果是一个闭包(忽略了适用于您的示例但并非一般情况下的优化)。
  • (*some list*)表示的代码是在some_function绑定到上述闭包的环境中进行评估的。
  • some_function s绑定到闭包且some_function绑定到s的计算结果的环境中计算表达式(*some list*)。在这种环境下,此评估成功,并且应用了闭包,这意味着现在将执行定义了some_function的代码(在已提供参数的环境中)。

闭包由未评估的代码和部分环境组成。仅需要为参数添加附加绑定来扩展环境,以便包含评估代码所需的所有内容。另一方面,只要未提供参数,就无法开始求值,因为函数的主体引用了参数。

some_function是递归的事实不会改变一般方案。这仅意味着在评估闭包的主体时,环境还包含将相同的some_function与闭包关联的绑定,因此对主体内部的some_closure的调用将以与处理闭包相同的方式处理。会在体外。