目前想到可以應用在 c/c# 沒辦法帶預設參數的情況上,像:
void func( int x, int y, int z ) { } void new_func1( int y, int z ) { return func( 1, y, z ); } void new_func2( int y, int z ) { return func( 2, y, z ); }
你可以想像到,這是一項複製、貼上的體力活,用 currying 的話,可以很快創造出新函數:
/* 以下為虛擬碼 */ void func( int x, int y, int z ) { } new_func1 = func(1); /* new_func1 仍是函數 */ new_func2 = func(2); /* new_func2 仍是函數 */
在 python 裡,透過 *arg、**kwargs 可以很容易實現,文章可以參考 Currying and Python, a practical example,裏面有點複雜,其實只要看 curry 類別的部份,下面就是直接摘錄出來的實例:
class curry: def __init__(self, fun, *args, **kwargs): self.fun = fun self.pending = args[:] self.kwargs = kwargs.copy() def __call__(self, *args, **kwargs): if kwargs and self.kwargs: kw = self.kwargs.copy() kw.update(kwargs) else: kw = kwargs or self.kwargs return self.fun(*(self.pending + args), **kw) def func( a, b, c ): print( a, b, c ) return (a+b+c) func1 = curry( func, 1, 100 ) func2 = curry( func, 2 ) print( func1( 200 ), func2( 300, 400 ) )
原理就是利用類別的特殊方法 __call__ ,呼叫 func2=curry( func, 2 ) 時,實際上是得到 curry 類別的實體。curry 類別的 __init__ 裡去做參數的判斷跟預存,等到把 func2 當函數執行時,就會執行到 __call__,這裡再去呼叫真正的函數。
沒有留言:
張貼留言