続・ラムダとY Combinatorと私。VBだって、やれば出来る子!
というわけで、前回の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