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# で頻繁に発生する一般的なパターンです。ある値に対して自分自身を再帰する内部関数が必要です。この関数は 1 回だけ必要です。何らかの方法で、その内部からラムダを呼び出すことは可能ですか?魔法のキーワードか何か)?コードを次のようにしたいと思います。

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

関数を1回だけ使用すると言いますが、技術的には2回名前で参照するため、名前を付けるのが理にかなっています。

于 2009-05-23T20:01:03.100 に答える