partial application

Python2.5でfunctoolsというモジュールが加わったらしい。全体は眺めてないけど,関数の部分適用とかできるみたい。

>>> from functools import *
>>> def foo( x, y, z ) :
...     return x + y + z
...
>>> add5 = partial( foo, 5 )
>>> add5( 2, 3 )
10
>>> add10 = partial( add5, 5 )
>>> add10( 5 )
15


そもそもOCamlだとこんなことは必要ないらしい。

> let foo x y z = x + y + z;;

val foo : int -> int -> int -> int

> let add5 = foo 5;; add5 2 3;;

val add5 : (int -> int -> int)
> val it : int = 10

> let add10 = add5 5;; add10 5;;

val add10 : (int -> int)
> val it : int = 15


Pythonのpartial関数もどきをLispで書いてみるとこんな感じ(?)でございましょうか。。。

CL-USER 1 > 
(defun foo (x y z)
  (+ x y z) )
FOO

CL-USER 2 > 
(defun partial (fn &rest env)
  #'(lambda (&rest args) (apply fn (append env args))) )
PARTIAL

CL-USER 3 > (let* ((add5 (partial #'foo 5))
                   (add10 (partial add5 5)) )
              (values (funcall add5 2 3)
                      (funcall add10 5) ))
10
15


C#だとちょっと苦しいかな。。。

public class Hoge
{
	public void Test()
	{
		Func<int, int, int, int> fn = ( x, y, z ) => x + y + z;
		var add5 = fn.Partial( 5 );
		Console.WriteLine( add5( 2, 3 ) );
		var add10 = fn.Partial( 5, 5 );
		Console.WriteLine( add10( 5 ) );
	}
}
public static class MyExtensions
{
	public static Func<TResult> Partial<T1, T2, T3, TResult>( this Func<T1, T2, T3, TResult> fn, T1 arg1, T2 arg2, T3 arg3 )
	{
		return () => fn.Partial( arg1, arg2 )( arg3 );
	}
	public static Func<T3, TResult> Partial<T1, T2, T3, TResult>( this Func<T1, T2, T3, TResult> fn, T1 arg1, T2 arg2 )
	{
		return ( x ) => fn.Partial( arg1 )( arg2, x );
	}
	public static Func<T2, T3, TResult> Partial<T1, T2, T3, TResult>( this Func<T1, T2, T3, TResult> fn, T1 arg1 )
	{
		return ( x, y ) => fn( arg1, x, y );
	}
}

こんな風に全部に対して書いていかなきゃならないかな?苦笑
何か別のエレガントな方法があるでしょうか。。。