代码之家  ›  专栏  ›  技术社区  ›  thr

F中的递归lambdas#

  •  7
  • thr  · 技术社区  · 17 年前

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

    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 "" 
    

    但是,正如您可能期望的那样,没有办法引用自身内部的匿名函数,这是我将递归的地方所需要的。##

    2 回复  |  直到 17 年前
        1
  •  17
  •   Dario    17 年前

    是的,可以使用所谓的 y-combinators (或) 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 entry 可能也会有帮助。

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

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

    let listToString lst =
    
        let rec loop acc = function
            | []    -> acc
            | x::xs -> loop (acc ^ (string x)) xs
    
        loop "" lst
    
        2
  •  1
  •   Daniel Earwicker    17 年前

    请注意,虽然您说只使用一次函数,但从技术上讲,您使用名称引用它两次,这就是为什么给它命名是有意义的。

    推荐文章