F# と C# の記法比較

MSDN F# リファレンスを使い C# と記法を比較する

ラムダ式: fun キーワード

ラムダ式: fun キーワード Lambda Expressions: The fun Keyword

元ネタ http://msdn.microsoft.com/ja-jp/library/dd233201.aspx

ラムダ式、つまり匿名関数を定義するには、fun キーワードを使用します。

F#

// Lambda expressions with parameter lists.
fun a b c -> ...
fun (a: int) b c -> ...
fun (a : int) (b : string) (c:float) -> ...

// A lambda expression with a tuple pattern.
fun (a, b) ->// A lambda expression with a list pattern.
fun head :: tail ->

C# でも書き方は似ている。fun キーワードはいらない。

C#

// parameter lists and tuple pattern
Func<int, string, float, int> f = (a, b, c) => 0;
// list pattern はこんな感じ?
Func<int, List<int>, int> f2 = (head, tail) => head + tail.Sum();

list pattern の場合は、head と tail を取り出せば良いので、こんな感じか?

expression は関数の本体であり、その最後の式によって戻り値が生成されます。 有効なラムダ式の例は次のとおりです。

F#

fun x -> x + 1
fun a b c -> printfn "%A %A %A" a b c
fun (a: int) (b: int) (c: int) -> a + b * c
fun x y -> let swap (a, b) = (b, a) in swap (x, y)

最後の swap は無理矢理 F# と同じように書くとこんな風になる。

C#

Func<int, int> f = x => x + 1;
Func<object, object, object, object> f2 =
    (a, b, c) =>
    {
        Console.WriteLine("{0} {1} {2}", a, b, c); return null;
    };
Func<int, int, int, int> f3 = (a, b, c) => a + b * c;
Func<object, object, object> f4 = (x, y) =>
{
    Func<Tuple<object, object>, Tuple<object, object>> swap =
        (t) =>
        {
            return new Tuple<object, object>(t.Item2, t.Item1);
        };
    return swap(new Tuple<object, object>(x, y));
};

ただし、内部で swap 関数を作る必要がなければ、Tuple を返すだけでよい。

C#

Func<object,object,Tuple<object,object>> f5 = 
    (a,b) => new Tuple<object,object>( b, a);

ラムダ式の使用

この場合は、匿名関数が、リストのすべての要素に 1 を追加します。

F#

let list = List.map (fun i -> i + 1) [1;2;3]
printfn "%A" list

C# には map 関数がないので自作するのだが、次のように拡張メソッドで作れる。ただし、拡張メソッドでは T が使えないので int 型限定。C# 6.0 ではジェネリックが使える予定なハズ。

C#

void test3()
{
    var lst = new List<int> { 1, 2, 3 };
    var dest = lst.Map(x => x + 1);
}
public static class ListExtensions
{
    public static List<int> Map( this List<int> src, Func<int,int> fn) {
        var dest = new List<int>();
        foreach (var it in src)
        {
            dest.Add(fn(it));
        }
        return dest;
    }
}

適用関数とリストの順序を守って、ListEx という新しいクラスを作ると T で書ける。

C#

void test4()
{
    var lst = new List<int> { 1, 2, 3 };
    var dest = ListEx<int>.Map(x => x + 1, lst);
}
public class ListEx<T>
{
    public static List<T> Map(Func<T, T> fn, List<T> src)
    {
        var dest = new List<T>();
        foreach (T it in src)
        {
            dest.Add(fn(it));
        }
        return dest;
    }
}