Recent discussion on Adding a test-framework to dao has brought my attention to python decorator. Previously I don't like much decorator, because it can arbitrarily change the logic of a program. But after thinking more about decorator, I start to be believe it offers more benefit than harm. Though decorator can be achieved in some way with Dao macro, having a native support could make decorator more intuitive and readable.

Python decorator is just a syntax sugar, which will replace the original function or class with whatever is returned by the decorator function. Such decorator is probably most easy to support, but I am not sure if this is the kind of decorator I want in Dao. I believe some semantic constraints should be added to decorators, to ensure what kind of function a decorator can be applied to, with certain minimum requirement on the interface of the resulting decorated function. I have got some ideas for function decorator, but still not sure about class decorator.

Basically, my idea is to support a new kind of function: decorator function , like:

this will will define a decorator that can be apply to functions whose parameters should be a superset of func_params , which will effective limit what kind of function this decorator can be applied to! Additionally the decorator can take parameters when it is applied to a function. As an example,

So here @mydecorator can be applied to any function that has a parameter named a with type string , and it will need take an integer as decorator parameter when it is applied. Such decoration will take place during compiling time, it will ensure typing safety of the decoration (function parameter types and returned type).

This syntax is quite reasonable for typed function decorator. Unlike python decorator, which is untyped and can be applied in the same way to classes, the proposed syntax here can not be naturally extended to classes (at least not in a equally simple way). Anyway, this might not be a big issue, I believe class decorator is much less useful than function decorator, it won't be a big problem if it is not supported.

Though untyped python decorator has simpler semantics and is easier to support, I prefer a typed decorator as it will make a better use of dao typing system:). However this is undecided yet, feedbacks are very welcome:)

Sounds promising. Just one thing: wouldn't it be better to use the native syntax for function argument in decorator? I mean original_func: routine<func_params> -- it would be clear and consistent. And also I think that not only parameters of decorated function should be checked, but its result type as well -- if it is specified in the decorator's function argument. Because theoretically such decorator may return anything, not only function result -- so the ability to restrict this aspect seems reasonable. Again, it would be nicer using the native syntax for routine type.

With the proposed syntax, @ mydecorator can be applied to any function with a parameter named a of string type. Using the native syntax for the function argument, which may imply that it can only be applied to functions with types conforming to the type of the decorator's function argument. Though we can make an exception here, it would look confusing. But I will consider to take this suggestion as a candidate alternative, since it may simplify the implementation:)

Well, if decorated function may have more parameters than specified in decorator argument, the syntax might be just the following: func: routine<a: string, ...> . But why the function parameter must necessarily be named a ?

It is to let the decorator to intercept some of the parameters passed to the original function and do what whatever necessary on the intercepted parameters. This explicitness is to allow the decorator to be compilable on its own.

If the native function type form is to be used, I would prefer func: routine<a: string> , because in any case we have to make an exception on interpreting the function type, to allow it to decorate a function with parameter list which is a superset of what in specified in the decorator's function argument without consideration of the ordering of the parameters.

Hmm, I have an idea which might possibly be realized via decorators, but I suppose not with the current ones proposed.

Suppose I have several routines which should perform the same operations before starting the execution of their own logic. For instance, several methods perform the same check regarding some class fields. Traditional way to simplify this would be to make an auxiliary function to carry this out:

Assuming that draw_some_figure and draw_another_figure may have completely different parameter lists, it seems impossible with the current state of the decorator concept (if I get it right). To put it simple, I think decorators could be used to construct custom modifiers for functions which might be useful for classes and routine libraries.

Sure it is possible, you just need to specify NO parameters for the function argument of the decorator, then it can be applied to any function with any parameter list. This is because any parameter list is a superset of an empty parameter list.

I like this feature -- very powerful, yet simple and nice. It is "the way of Dao", I suppose :) All in all, a good idea and a major enhancement.

It's interesting to me: if decorator has an additional argument with a default value, then decorator's short form should be @decorator() or just @decorator ? And another thing: should decorator be allowed to be called explicitly as @decorator(func(a, b)) ?

Glad you like it and feel it simple, I hope other people, especially people used to python decorator, will find it simple too:)

Currently @decorator() is treated the same as @decorator , it should be less confusing. I agree that decorator should be allowed to be called explicitly, but @func(params) in expression was previously used for creating an instance of coroutine and generator. We need to find a new syntax for them.

I have one suggestion to bring it to the next level and make it even more useful. If it could be applied to an existing routine, without modifying it at all, in order to create a new routine. This would be very powerful. Let me explain.
It often happens that there is some 3rd-party module that you happen to use, and it has that great function you would like to connect with some other 3rd-party module. But unfortunately, the signature doesn't fit, or it needs one more parameter or whatever. To solve this problem, there are design patterns like "wrapper" or "adapter". But we know by now that a design pattern is just a workaround to missing language support.
Something around this, with decorators, might solve it in Dao: (The example is not the best, but I had no better idea right now)

Now, I hope this example made it clear: I can apply a decorator to an already existing routine, creating a new one. The example was really not good and now I think a better example would go with the "logging" decorator, then you might want to log existing 3rd-party routines too, but can't change the code. Being able to add the decorator like in my example above would solve it. I try it again:

Supposing doTheGreatThing and doEvenGreaterThings are from 3rd-party modules, then they can be overrode in the current module and in the downstream modules that load this one. So the above codes effectively redefine these two functions in the current namespace.

Change picture:

Choose file:

This site is powered by Dao
Copyright (C) 2009-2013, daovm.net.
Webmaster: admin at daovm dot net