2010年10月11日

C#でunfold

   このエントリーをはてなブックマークに追加 Clip to Evernote
T_GYOUTENさんの記事 に触発されて、C#で3つのUnfold関数を書いてみました。

名前をどうしようか迷ったのですが、Unfoldクラスを定義し、そこに Do メソッドを定義
することにしました。一つの機能しかないstaticクラスを作る時には、名前をどうするか
悩みますね。
引数の順番は、F#とは逆にし、初期値, generator の順にしました。

まずは、一つ目のバージョンのUnfold.Doメソッド
使い方はこんな感じ。
true, false が繰り返されます。
generatorが null を返すと終了しますが、Tが値型の場合、nullがとれないので、
無限に繰り返すことになります。

2つめは、繰り返し条件を指定できるバージョン。これならば、値型でも有限のシーケンスを 得ることが できます。
使い方です。
1 2 4 8 16 32 64 128 256 512 と表示されます。

最後は、最も汎用性のあるバージョンで、F#のSeq.unfoldとほぼ同等のものです。
Tupleを使っているので、ちょっと分かりにくいかもしれませんが、
これだと、初期値に与える型と、戻り値の各要素の型を別のものにすることができます。

以下、使い方の例です。
true, false を繰り返しています。 これだと、最初に示した true, false を返すコードのほうが簡単なので、
このTuple使ったDoメソッドだからできる例を示します。
フィボナッチ数列を求めるコードです。
unfoldは強力ですが、使うにはちょっと慣れが必要ですね。

  

Posted by gushwell at 21:25Comments(2)TrackBack(0)

2010年09月23日

2つの配列から「値のペア」を列挙する

   このエントリーをはてなブックマークに追加 Clip to Evernote
F#の記事を書いて思ったんですが、C#でも、2つの配列にある値から「値のペア」を列挙するような場面は結構あるなーと。

いろんな書き方が考えられるので、例として、Dictionayに値を追加するコードをいくつか試しに書いてみました。
すぐに思い浮かぶのが、for文を使った書き方。これが、一番簡単ですね。

でも、{ ] の中がもっと複雑で、インデックスによるアクセスが複数個所で必要になる場合は、
for 文は、面倒だなーって感じることがあります。
foreach 使いたいなーと思っても、
とか書くと、alpstrの各要素にアクセスできないし、
とか書ければいいんですが、できません。

それと、LINQ使いたいな、というときには、インデックスを使うやり方は使えません。

.NET Framework4だと、Enumerable.Zip があるので、こういった時に使えそうです。

でも、最後の引数のSelectorがめんどくさい。

Tuple が追加されたのだから、

という Tuple 決め打ちのメソッドが標準で用意されてもよかったのにと思います。
そうすれば、以下のようなコードが書けます。

Tuple 嫌いだという方は、C#4.0で導入された dynamic 使って、こんなメソッドを書きます。
IEnumerableジェネリックスの型指定を dynamic にして、匿名クラスのオブジェクトを返しています。
すると、以下のように、書けます。
実際、Tuple使わない理由もないので、このZip2はあまり意味ないですが、dynamic の可能性の一つとして 見てもらえればと思います。

最後に、再度断っておきますが、
ここで問題にしているのは、Dictionayオブジェクトに値を追加する方法ではなくて、
2つのコレクションから、値のペアを列挙する方法です。

10/24 追記

意外にも反応がたくさんあってびっくりしました。
何人かの方が、コメントやトラックバックで、別の解法を示してくれて 僕も勉強になりました。
いろいろな書き方があるってことは、C#が表現力豊かな言語である証ですね。

なお、この記事を最初にアップしたときには、

>それと、LINQ使いたいな、というときには、このやり方は使えません。

と書きました。その後、

>それと、LINQ使いたいな、というときには、インデックスを使うやり方は使えません。

と書き直しましたが、
これは、for 文だと、続けて LINQの拡張メソッドに続けられないけど、Zipなどを使えば、
そのあとに、Where や Select や Count などが続けられる、という意図でした。
LINQでは、「2つの配列から値のペアを列挙することができない」という意図で、
書いたのではなかったのですが、僕の表現のあいまいさのおかげ(?)で
いろんなコードを見ることができました。
  
Posted by gushwell at 17:12Comments(3)TrackBack(2)

2010年09月20日

これは反変性の例なのかな?

   このエントリーをはてなブックマークに追加 Clip to Evernote
Microsoftのサイトにある、『連載! とことん C#』の 第 11 回 共変性 (covariance) と反変性 (contravariance) ですが、

ここの「2.共変性と反変性」で説明している反変性の例は適切なのでしょうか?
そのコードを抜粋させていただきます。
なんか、ここで説明しているコードは、反変性の例になっていないような気がするのですが...
どなたかわかれば教えてください。

僕の理解では、C#で、こんな単純なコードで反変性を説明するのは 無理なんじゃないかと...
それとも、僕が知らないだけですか?   
Posted by gushwell at 22:34Comments(6)TrackBack(0)

2010年03月07日

C#4.0 : dynamicを使いジェネリックスで加算減算をする

   このエントリーをはてなブックマークに追加 Clip to Evernote
メールマガジン「C#プログラミングレッスン」No243では、 どう書くorgで出されているお題「隣り合う二項の差」のコードを示しました。
その以下に示します。


このメソッドは引数に、 int[], List<int>などは受け取れますが、double[], List<long>などは 受け取れません。


というジェネリックメソッドにしたとしても、


で、減算ができないため、コンパイルエラーになってしまいます。 このエラーを取るには、C#3.0では、力づくで場合分けするなどする必要があります。
参考URL:http://gushwell.ldblog.jp/archives/51533037.html

しかし、C#4.0ななると、dynamic型が導入されるので、 以下のように、書くことができます。


この機能があることで、ジェネリックの応用範囲がさらに広げられそうです。
  
Posted by gushwell at 21:10Comments(2)TrackBack(0)