読者です 読者をやめる 読者になる 読者になる
ようこそ。睡眠不足なプログラマのチラ裏です。

続・ラムダとY Combinatorと私。VBだって、やれば出来る子!

プログラミング アルゴリズム LINQ VB.NET

というわけで、前回のC#3.0で書いたラムダとY Combinatorと私。Y Combinatorは恐ろしい子。について、
VB2008のラムダ式でも書いてみました。VBだってやれば出来る子なんです(´・ω・`)

Imports System
Imports System.Linq
Imports System.Collections.Generic

Module Module1

    Sub Main()
        'エラトステネスの篩(素数求めるやつ)
        Dim sieveOfEratosthenes As Func(Of IEnumerable(Of Integer), IEnumerable(Of Integer)) = _
            Fix(Of IEnumerable(Of Integer), IEnumerable(Of Integer))(Function(fact) Function(nums) _
                From num In nums _
                Where num = nums.First() Or num Mod nums.First() <> 0 _
                Select num _
            )

        For Each s As String In sieveOfEratosthenes(Enumerable.Range(2, 98))
            Console.WriteLine(s)
        Next
        Console.ReadLine()
    End Sub

    ''' <summary>
    ''' Y Combinator
    ''' </summary>
    Delegate Function Recursive(Of T, TResult)(ByVal f As Recursive(Of T, TResult)) As Func(Of T, TResult)
    Function Fix(Of T, TResult)(ByVal lambda As Func(Of Func(Of T, TResult), Func(Of T, TResult))) As Func(Of T, TResult)
        Dim y As Func(Of Func(Of Func(Of T, TResult), Func(Of T, TResult)), Func(Of T, TResult)) = _
        Function(f) (DirectCast((Function(g) Function(x) f(g(g))(x)), Recursive(Of T, TResult))) _
                    (DirectCast((Function(g) Function(x) f(g(g))(x)), Recursive(Of T, TResult)))
        Return y(lambda)
    End Function

End Module


C#3.0のlambda式は、式だけではなく、メソッドのように{}で囲った中にステートメントを書くことができるが、
VB2008のlambda式は、単一の式しか書くことができない点が異なる。
2chのスレなんかでは「VBのラムダ使えねぇw」との声が多いですね。
使えないとまでは言わないけど、マニアックなことをしたい人にはきつい制約かもかも。
ラムダ使うなら断然C#3.0といった感じ。



ついでに、匿名型に関してのC#3.0とVB2008との違いについてもちょっと言及。
C#3.0では、宣言時に初期化した内容を書き換えることができない(ReadOnly)が、
VB2008では、宣言時に初期化した内容を書き換えることができる。
VB2008で、宣言時の内容を書き換えたくないような場合はキーワード指定でReadOnlyとすることができる。
匿名型に関しては、VB2008の方が柔軟というわけか。
C#3.0の言語仕様は、なんで匿名型の内容を書き換えられないようにしたんだろう。ふーむ。



#ん〜、今更こんなこと言うのも野暮って話なんだが、
VBは改行すると「_(アンダースコア)」を書かなきゃならんっちゅー仕様があるが、ここにきて邪魔な感じ。
#普通にコード書いている分には、さほど問題にはならないが、
#ラムダ書いたり、LINQ書くときは「_(アンダースコア)」が大量に必要になって、ウザすぎるってゆー。
#何度もFunctionって書くのは冗長だし、ジェネリクス併用してカッコやらOfも書くとなってくると更にきっつい。
C#でさえ見難いのに、VBのこの見難さ(醜さ)は、マジで泣けてくるレベル。上記Y Combinatorは、その典型例だろう。
VBでは、ラムダとかLINQは使うなっちゅーことなんでしょうか。
VBユーザーいじめですか?そうじゃないと思いたい(^ω^;)




(追記:2008/08/26)

なんか無駄にややこしく書いてましたね(^ω^;)
こー書けばVBでもそこそこ見やすいかも。

    ''' <summary>
    ''' Y Combinator
    ''' </summary>
    Delegate Function Recursive(Of T, TResult)(ByVal f As Recursive(Of T, TResult)) As Func(Of T, TResult)
    Function Fix(Of T, TResult)(ByVal f As Func(Of Func(Of T, TResult), Func(Of T, TResult))) As Func(Of T, TResult)
        Dim r As Recursive(Of T, TResult) = Function(g) Function(x) f(g(g))(x)
        Return r(r)
    End Function