8

以这个示例代码为例(暂时忽略它非常低效)

let listToString (lst:list<'a>) = ;;' prettify fix

    let rec inner (lst:list<'a>) buffer = ;;' prettify fix
        match List.length lst with 
        | 0 -> buffer
        | _ -> inner (List.tl  lst) (buffer + ((List.hd lst).ToString()))

    inner lst ""

这是我在 F# 中经常遇到的一种常见模式,我需要一个内部函数,它在某个值上递归自身 - 我只需要这个函数一次,有没有可能从它自身内部调用一个 lambda(一些魔术关键字或其他东西)?我希望代码看起来像这样:

let listToString2 (lst:list<'a>) = ;;' prettify fix

    ( fun 
        (lst:list<'a>) buffer -> match List.length lst with ;;' prettify fix
                                 | 0 -> buffer
                                 | _ -> ##RECURSE## (List.tl lst) (buffer + ((List.hd lst).ToString())) 
    ) lst "" 

但是正如您可能期望的那样,没有办法在其内部引用匿名函数,这是我放置##RECURSE##的地方所需要的

4

2 回答 2

19

是的,可以使用所谓的y 组合器(或fixed-point combinators)。前任:

let rec fix f x = f (fix f) x

let fact f = function
 | 0 -> 1
 | x -> x * f (x-1)


let _ = (fix fact) 5 (* evaluates to "120" *)

我不知道 F# 的文章,但这个haskell 条目可能也有帮助。

但是:如果有其他选择,我不会使用它们——它们很难理解。

您的代码(此处省略类型注释)是标准构造,并且更具表现力。

let listToString lst =

    let rec loop acc = function
        | []    -> acc
        | x::xs -> loop (acc ^ (string x)) xs

    loop "" lst
于 2009-05-23T19:40:20.273 回答
0

请注意,尽管您说您只使用该函数一次,但从技术上讲,您两次通过名称引用它,这就是给它一个名称的原因。

于 2009-05-23T20:01:03.100 回答