[NAME]
ALL.misc.comparison.decorator

[TITLE]
Function Decorator (Python)

[DESCRIPTION]

Decorators are a special type of functions that can be used to enhance the functionaliti
es 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 r
eplacement functions, instead, they are defined as the templates from which the replaceme
nt 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 c
an 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 c
an 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 m
ust expand the previous tuple argument in the argument list, namely, removing the tuple a
nd placing its items in the argument list.

In both Python and Dao, decorators can be applied at function definition sites in the sam
e way.

 0.2   Decorators for Any Functions  

If one wants to define a decorator that can be applied to any functions. In Python, one m
ight 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 hav
e to create decorators as in the above Python examples and check the argument types to ha
ndle 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.