[NAME] ALL.misc.comparison.decorator [TITLE] Function Decorator (Python) [DESCRIPTION] Decorators are a special type of functions that can be used to enhance the functionalities of other functions by decorating them. 0.1 Decorators for Single Functions In Python, a decorator is just a callable that can take a function as an input argument and return a replacement function as output. For example, 1 def Decorator( func ): 2 def newfunc(): 3 ret = func() 4 return ret + 123 5 return newfunc 6 7 def Foo(): 8 return 456 9 10 deco = Decorator( Foo ) 11 deco() Dao decorators are quite different from Python decorators. Dao decorators do not return replacement functions, instead, they are defined as the templates from which the replacement functions can be created. Such replacement functions may or may not call the original function, this is the same as Python decorators, but Dao decorators are typed and can be strictly typed. So all the static type checking that can be applied to normal functions can also be applied to decorators as well. An equivalent Dao decorator for the above Python example is, 1 routine @Decorator( func(args) : routine< =>int > ) 2 { 3 ret = func( args, ... ) # call the original function; 4 return ret + 123 5 } 6 routine Foo() 7 { 8 return 456 9 } 10 deco = @Decorator( Foo ) 11 deco() Where the parameter type routine< =>int > of @Decorator() indicates that this decorator can only be applied to functions that can take no parameter and return an integer. args is a specially defined variable of tuple type to hold the parameters that will be passed to the decorated function. The ... in the end of the argument list indicates that the call must expand the previous tuple argument in the argument list, namely, removing the tuple and placing its items in the argument list. In both Python and Dao, decorators can be applied at function definition sites in the same way. 0.2 Decorators for Any Functions If one wants to define a decorator that can be applied to any functions. In Python, one might do, 1 def Decorator( func ): 2 def newfunc( *args, **kwargs ): 3 print "Calling with: %s, %s" % (args, kwargs) 4 return func( *args, **kwargs ) 5 return newfunc 6 7 def Foo( a ): 8 return a + 456 9 10 deco = Decorator( Foo ) 11 deco( 123 ) The equivalent in Dao would be, 1 routine @Decorator( func(args) : routine ) 2 { 3 io.writeln( 'Calling with:', args, ... ) 4 return func( args, ... ) # call the original function; 5 } 6 routine Foo( a ) 7 { 8 return a + 456 9 } 10 deco = @Decorator( Foo ) 11 deco( 123 ) 0.3 Overloaded Decorators If one wants to write a decorator for multiple type of functions, in Python one would have to create decorators as in the above Python examples and check the argument types to handle different types of functions. Because Python does not support function overloading. In Dao, one could simply create different decorators for different target functions, and overload them with the same name. For example, 1 routine @Decorator( func(args) : routine<int=>int> ) 2 { 3 return func( args, ... ) + 123 4 } 5 routine @Decorator( func(args) : routine<string=>string> ) 6 { 7 return func( args, ... ) + 'abc' 8 } 9 10 @Decorator # the first decorator will be applied; 11 routine Foo( a : int ) 12 { 13 return a * 100 14 } 15 16 @Decorator # the second decorator will be applied; 17 routine Foo( a : string ) 18 { 19 return a + '##'; 20 } 21 22 f = @Decorator( Foo ) 23 f( 123 ) 24 f( 'xyz' ) When the target function is also overloaded, the decorator will be applied to each of the overloaded functions, and create a new (and possible also overloaded as well) function.