すがブロ

sugamasaoのhatenablogだよ

yield を使ってみる

Ruby では

yield を実装すること自体は、そんなにしょっちゅう無いかもしれないけど yield を使うことはしょちゅうだ。
each 構文無しではもはや生きられない体になっているといっても過言ではない。

そこで

自分でもちょっと実装できるように調べてみた。
ついでに、 C# ではどうやるのかも調べた。

以下実験ソース

はっきりいって何の役にも立たないけど、とりあえず構文の動きはつかめるようになった。

def yield_test (csv)
  csv.split(",").each do |data|
    yield data.strip unless data == ""
  end
end

csv = "test, one, 123, \"test\", asfd,,sdf"

yield_test(csv) do |line|
  print "[#{line}]\n"
end
using System;
using System.Collections.Generic;

namespace yieldTest
{
    class Program
    {
        static IEnumerable<string> yieldTest(string csv) {
            foreach (string data in csv.Split(','))
            {
                if (data != "")
                {
                    yield return data.Trim();
                }
            }
        }

        static void Main(string[] args)
        {
            string csv = "test, one, 123, \"test\", asfd,,sdf";

            foreach (string line in yieldTest(csv))
            {
                Console.WriteLine("[{0}]", line);
            }
        }
    }
}
  • 実行結果(どっちも一緒)

[test]
[one]
[123]
["test"]
[asfd]
[sdf]

解説

yield メソッド(?)に渡した変数の値が yield を実装しているメソッドの呼び出し元へ返される。
Ruby ではブロック構文(っていうのか?)である

line

の部分に yield に渡した値が入る。
C# ならコレクション(IEnumerableな値)をyield return で返してやる。 yield と foreach(コレクションと foreach?)は、ほとんどワンセットみたいな感じなので、yield を呼び出すときは

foreach (type var in コレクション)

で呼び出して、 var の部分に値が入ると覚えておくと良いだろう。
ちなみに、C# には yield break っていう構文もあって、 文字通り処理を中断する構文のようだ。
たとえば、ある配列をずっと見ていて、 null オブジェクトがあったら yield の処理を終わらせる(yield break する)とかに使えば良いのだろう(と思う)。

というわけで

思ったよりも簡単に両者とも同じ動作のプログラムを作ることができた。
でも、ぶっちゃけた話、どういう時に yield を実装したくなるのかよくわかんない(´Д`)