はじめてのLINQ

LINQ Previewをダウンロードして実験君。ただ、日本語版VS2005β2には対応していないようなので、コマンドラインからちまちまコンパイルすることに。

using System;
using System.Query;

class Program {
    public static void Main () {
        var src = new int [] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        var dst = from n in src
            where n % 2 == 0
            orderby n descending
            select n;
        foreach (var n in dst)
            Console.WriteLine (n);
    }
}

/* 結果
8
6
4
2
 */

さっくり動きますね。なんだか凄そうに見えますが、コイツをC#2.0のコードで書くと、

using System;
using System.Query;

class Program {
    public static void Main () {
        int src = new int  { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

        OrderedSequence<int> os = 
            Sequence.OrderByDescending<int, int>(
                    Sequence.Where<int>(src, delegate (int n) { return n % 2 == 0; }), 
                    delegate (int n) { return n; });
        foreach (int n in os)
            Console.WriteLine (n);
    }
}

意外と単純。イメージ的にはUnixのパイプに近いかな。

$ from n in src | where | orderby | select > dst

↑こんなのを想像してみてください。

そーいや、queryの並びがSQLと異なって(selectが最後に来ている)いますが、これについてヘジたんがビデオでコメントしていたけど、VB9のLINQってSQLの並びなんですよね。この辺は統一取れてないのかしら?(^^;

Lambda expressions

C#3.0のLambdaがシンプルで良い感じなので、Nemerleでも真似出来ないかと色々試すも、私の知識じゃ歯が立たず。あんまマクロ分かってないんですよね。(^^;

で、格闘の跡。

using Nemerle.Compiler;

// 引数1つ
macro @fx (parm : parameter, body)
    syntax ("fx", parm, "->", body)
{
    match (parm) {
        | <[ parameter: $(iname : name) : $ty ]> =>
          <[ fun ($ (iname : name) : $ty) { $body } ]>
        | _ => Message.FatalError ("excepted a single parameter")
    }
}

// 引数2つ
macro @fy (parm1 : parameter, parm2 : parameter, body)
    syntax ("fy", parm1, parm2, "->", body)
{
    match (parm1) {
        | <[ parameter: $(iname1 : name) : $ty1 ]> =>
            match (parm2) {
                | <[ parameter: $(iname2 : name) : $ty2]> => 
                    <[ fun ($ (iname1 : name) : $ty1, $ (iname2 : name) : $ty2) { $body } ]>
                | _ => Message.FatalError ("excepted two parameters");
            }
        | _ => Message.FatalError ("excepted two parameters")
    }
}

使い方は、こんな感じ。

def f1 = fx x -> x * 2;
def f2 = fy x y -> x + y * 2;
def f3 = fy a b -> a * 2 + b;
Nemerle.IO.printf("%d\n", f1 (10));
Nemerle.IO.printf("%d\n", f2 (10, 20));
Nemerle.IO.printf("%d\n", f3 (10, 20));

/* 結果
20
50
40
 */