2009-05-23 34 views
7

は、この例のコードを取る再帰的なラムダ

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#で渡って来続ける一般的なパターンがある(それは一瞬のために恐ろしく非効率的であることは無視)、私は自分自身を再帰的内部機能を持っている必要がありますいくつかの価値を超えて - そして、私はこの機能を一度しか必要としません、そこにラムダを呼び出すことが可能です(いくつかの魔法のキーワードか何か)?私は## RECURSE ##

答えて

17
を置く場所が必要である

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

しかし、あなたが自分自身の中に無名関数を参照する方法がない想像のとおり、私はコードをこのような何かを探すためにしたいと思います

はい、それはいわゆる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" *) 

Iは、F#のための記事を知らないが、このhaskell entryも役に立つかもしれません。

しかし、代替手段がある場合は、私はそれらを使用しません。彼らは理解しにくいです。

あなたのコード(ここでの型の注釈は省略しています)は標準的な構造であり、はるかに表現力があります。

let listToString lst = 

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

    loop "" lst 
1

あなたは一度だけの機能を使用すると言うが、技術的に、あなたはそれに名前を付けることは理にかなって理由である、二回名前で参照することに注意してください。