8 ms·
Decorators are ways to wrap function definitions with code that gets executed at the time the function is defined. Commonly they add stuff that happens every t
by jfm3 16y ago
Decorators are ways to wrap function definitions with code that gets executed at the time the function is defined. Commonly they add stuff that happens every time the function is called.
This is certainly something you can do with macros, but it's not even really close to the full semantics. Macros allow you to add new special forms to the language. If Python had macros, for example, the new `with` statements would have been a five line addition to the standard libraries.
I really don't see it as "damned close" at all.
- euccastro 16y agoDefinitely. Indeed decorators are a patch to a shortcoming in Python's ability to define anonymous functions or classes. If you could just say something like: f = memoized(lambda x, y: ... some multiline function) or C = coords_or_vectors(class: ... some class definition) you wouldn't need the kludge: @memoized def f(x, y): ... @coords_or_vectors class C: ... Note that I'm not arguing for the syntax in the first two examples, just the ability to do the equivalent without special cases in the normal syntax of the language. In Scheme you wouldn't need to learn the extra syntax, learn and remember the order in which decorators apply (top to bottom?, inner to outer?). I was actually very happy when decorators got added to Python. But let's face it, they just give you a way out of a corner Python painted itself into. They're nothing to be too proud of.
- softbuilder 16y ago"Damned close" perhaps should be qualified as from the point of view of a Pythonista, given the ideals of that approach to programming. I took issue with the specific point that Python "has no macros", and then I qualified it, knowing full well that Lisp macros do more. Decorators ultimately result in a function that is a substitute for another function. That function can have all sorts of wonderful runtime behavior, including access to arguments, the call stack, and other functions. Dismissing them as "adding stuff that happens every time the function is called" misses an entire dimension of their utility.
- euccastro 16y agoSorry to be blunt, but it's only "damned close" from the point of view of someone that doesn't understand either decorators or macros. Decorators are syntactic sugar for a particular mix of assignment and function call. They're just there so you only need to write the name of the decorated object (say, function or class) once rather than three times. For example @some_deco def f(a, b): return a+b Is exactly the same as def f(a, b): return a+b f = some_deco(f) Let me repeat: decorators only save you writing the name of the function two additional times. Which is nice and worth it, but not groundbreaking, and, more to the point, has nothing whatsoever to do with macros (except perhaps that in Python you couldn't do it without macros, but that's besides the point). The equivalent to decorators in Lisp is just normal higher order programming (functions taking functions as arguments, and/or returning functions), with no particular syntax. (define f (some-deco (lambda (a b) (+ a b)))) It would be bad form to use a macro for something like this, which is firmly within the domain of normal function definitions and calls. (P.S.: For short functions like this, you could have said, in Python: f = some_deco(lambda x, y: x + y) But this breaks for multiline functions and class definitions.)
- softbuilder 16y agoYou're conflating decorator syntax, which I'm not discussing, and decorator functionality, which I am discussing. If there was no syntax for decorators and the only way to decorate a function was to use assignment/composition like in your example, I would still consider that to be a decorator. A macro is going to be evaluated at compile time and will result in a matching pattern (often something that is structured like a function call) being expanded into some other construct that will be evaluated at runtime. A decorator is going to be evaluated at compile time and will result in a decorated function being "expanded" into another function which will be evaluated at runtime. No, they aren't the same thing. How could they be? The languages are different. But there is an underlying affinity.
- euccastro 16y ago> You're conflating decorator syntax, which I'm not discussing, and decorator functionality, which I am discussing. Guilty as charged. I admit I thought you were talking about decorator syntax. Because decorator-the-technique makes even less sense as an alternative to macros. Decoration is a technique of higher order programming (taking functions as arguments and/or returning them). The fact that you can use it at "compile time" (whatever that means in Python) is a property of the dynamic nature of the language. Yes, that stuff is powerful. But Scheme has all that, and its designers still saw the need to add macros, mostly to do the things that you can't do by executing higher order functions at "compile time". Macros are not essentially about doing stuff at compile time; they're about messing with the very syntax of the language. My point is not just that decorators and macros aren't the same thing; it's that macros are meant explicitly to do what decorators can't. I guess most Python programmers don't miss macros simply because they've never seen the need for them in first place, not because Python has any replacement. The closest alternative that Python has to macros would be eval. In my opinion, what ultimately allows most Python programmers who have been exposed to macros to almost never miss them is the syntactic sugar that the Python authors keep (judiciously) adding every release.