F#如何实现letrec?

asa*_*afc 5 parameters recursion scheme f#

我想知道 F# 是如何实现的let rec,但我找不到答案。作为前言,我将介绍一下 Scheme 是如何实现的letrec

  1. 在Scheme中,let只是lambda定义和应用的语法糖:

(let ((x 1)) (+ x 2))

变换为

((lambda (x) (+ x 2)) 1)

(在每种情况下,表达式的计算结果为3)。

  1. letrec也是语法糖,但#f作为初始参数传递给 lambda 的参数,并且set!表达式在主体之前注入letrec,就像在这个转换中一样:

(letrec ((x 1)) (+ x 2)) => ((lambda (x) (begin (set! x 1) (+ x 2))) #f)

考虑到F#没有与Scheme等效的运算符set!,它是如何实现的let rec?它是否将函数的参数声明为mutable,然后在函数体内对它们进行变异?

Ast*_*sti 4

在 F# 中,let rec允许在绑定之前从函数内部引用绑定。let rec本身没有实现,因为它只是编译器提示。

在这个人为的例子中,

let rec even =
    function 0 -> true  | 1 -> false | x -> odd (x - 1)
and odd =
    function 0 -> false | 1 -> true  | x -> even (x - 1)
Run Code Online (Sandbox Code Playgroud)

编译后的 IL 非常平庸地翻译为:

public static bool even(int _arg1)
{
    switch (_arg1)
    {
    case 0:
        return true;
    case 1:
        return false;
    default:
        return odd(_arg1 - 1);
    }
}

public static bool odd(int _arg2)
{
    switch (_arg2)
    {
    case 0:
        return false;
    case 1:
        return true;
    default:
        return even(_arg2 - 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

所有函数定义都静态编译为 IL。F# 最终是一种运行在 CLR 上的语言。没有元编程。