request: python style decorators / aspect orientation

Chris Nicholson-Sauls ibisbasenji at gmail.com
Thu May 10 00:14:42 PDT 2007


Daniel Keep wrote:
> 
> Nicolai Waniek wrote:
>> Hi everyone,
>>
>> Hopefully a few of you knew the python style decorators (python's version of
>> aspect orientation):
>>
>>
>> def aspectFunc(f):
>>     def wrapper():
>>         print "log before function call"
>>         f()
>>         print "log after function call"
>>
>>     return wrapper
>>
>> @aspecFunc
>> def myfunction():
>>     print "hello world"
>>
>>
>> Would it be possible to have something like this in D? IMHO it would make code
>> more clear. For example it could look like this when decorating a function:
>>
>>
>> version (debug) {
>>     @logFunc
>> }
>> void myFunction(int param0)
>> {
>>     // do something here
>> }
>>
>>
>> instead of:
>>
>> void myFunction(int param0)
>> {
>>     version (debug) {
>>         logthis("blabla");
>>     }
>>     // do something here
>>     version (debug) {
>>         logthis("finally we reached an end here");
>>     }
>> }
>>
>> I think it would take all the bloat out of functions that doesn't really belong
>> to the function. I don't know how much work it would be to implement such a
>> thing, but I think there would be many cases this could be usefull. If this is
>> already possible in a sane way, please let me know as this is one of the
>> features I do like most in python and would like to have in D.
>>
>> Best regards,
>> Nicolai
> 
> This is just a quick hack, but it does work.  The main problem is that
> you have to put the logFunc alias *after* the function is defined, or
> you get forward-reference errors.
> 
> Apart from that, it should do what you want.
> 
> 	-- Daniel
> 
> -----
> 
> module fnwrap;
> 
> import std.stdio;
> import std.traits;
> 
> void logthis(char[] msg)
> {
>     writefln("LOG - %s", msg);
> }
> 
> ReturnType!(typeof(fn)) logFunc(alias
> fn)(ParameterTypeTuple!(typeof(fn)) args)
> {
>     alias ReturnType!(typeof(fn)) returnT;
>     debug
>     {
>         logthis("ENTER - "~(&fn).stringof);
>         scope(exit) logthis("EXIT  - "~(&fn).stringof);
>     }
>     static if( is( returnT == void ) )
>         fn(args);
>     else
>         return fn(args);

Actually you can leave this check out, as I recall.  Returning values in void-return 
functions is allowed, and I would infer (haven't tested, however) that returning a void 
from a void() would also be fine.  Could be wrong.

> }
> 
> void myFunction_(int param0)
> {
>     writefln("Do something with %s...", param0);
> }
> alias logFunc!(myFunction_) myFunction;
> 
> void main()
> {
>     myFunction(42);
> }
> 

Overall a neat and useful trick.

-- Chris Nicholson-Sauls



More information about the Digitalmars-d mailing list