事例:文字列を反転する

関数 reduce を使うと、その順序を逆にした文字列が得られます。

>>> reduce(lambda acc,e: e+acc, "ABC")'CBA'

ここでは、"C"+("B"+("A")) という過程を経て、反転した文字列 'CBA' が得られます。ただし、文字列を反転させるだけなら、次のようにして、

>>> "ABC"[::-1]'CBA'

スライスを利用するのが定石のひとつです。

>>> reduce(lambda acc,e: e+acc, "", "@")'@'

空文字列 "" を与えると、初期値 "@" がそのまま、リターン値として得られます。

インターフェース:IEnumerator

メソッド本体を見ると、次に示す典型的な C# のイディオムが記述してあります。

    IEnumerator e = ...
while (e.MoveNext()) { // 次の要素に進んで
... e.Current ... // その要素を参照する
}

《参照》インターフェース IEnumerator の詳細は、http://msdn.microsoft.com/en-us/library/system.collections.ienumerator_members.aspx を参照してください。□
インターフェース IEnumerator で規定したプロトコルに従って、各要素 e を順に参照します。

    IEnumerator i = Ops.GetEnumerator(seq);

ここでは、シーケンス seq からどのようにして IEnumerator が得られるか(how)は知らなくても、それを使ってなにをしたいか(what)を理解できれば、十分です。seq の各要素を参照したいときに、Ops.GetEnumerator を利用するだけです。

    ret = Ops.Call(func, ret, i.Current);

ここでは、関数 func を呼び出すときに、2つの引数 ret および i.Current が必要になることを理解できれば、十分です。関数 func(ret, i.Current) を呼び出したいときに、Ops.Call を利用するだけです。引数 ret に初期値を与え、i.Current は次の要素を参照します。そして、変数 ret は、関数のリターン値を保持します。


Previous〈2/5〉Next

ソースコード:Reduce(object, object, object)

関数 reduce の定義を含む、ソースコードの断片を次に示します。

# IronPython-1.1.2/Src/IronPython/Modules/Builtin.cs
[PythonType("__builtin__")]
public static partial class Builtin {
...
[PythonName("reduce")]
public static object Reduce(object func, object seq, object initializer) {
IEnumerator i = Ops.GetEnumerator(seq);
object ret = initializer;
while (i.MoveNext()) {
ret = Ops.Call(func, ret, i.Current);
}
return ret;
}

クラス Builtin のヘッダーを見ると、ここに組み込み関数が定義されているのが分かります。次に、静的メソッド Reduce のヘッダーを見ると、関数 reduce の各引数に相当するのが分かります。