4 ms·
Re: 8, you don't need decorators to compose functions: def comp(f, g): def h(*args, **kwargs): return g(f(*args, **kwargs)) # f
by leif 16y ago
Re: 8, you don't need decorators to compose functions:
def comp(f, g):
def h(*args, **kwargs):
return g(f(*args, **kwargs))
# fix up h.__doc__ and friends
return h
or simply
(lambda the, args: g(f(the, args))(x, y)
(don't remember comp's semantics, is (comp f g) = f o g or g o f?)
too long; don't read:
Decorators are certainly cool, but semantically they represent something more like a pattern than a FP construct. A decorator represents something you might want to do to lots of functions, a property you want all instances of a function to have without writing it explicitly into each function. Function composition is more along the lines of having two functions which are interesting on their own, but which sometimes you want to compose.
With decorators, it would also be awkward to compose multiple functions. Observe:
def compose_with(g):
def decorator(f):
def decorated_function(*args, **kwargs):
return g(f(*args, **kwargs))
return decorated_function
return decorator
def h(x): math.sqrt(x)
@compose_with(h)
def g(x): 2 * x
@compose_with(g)
def f(x): x + 1
versus (for some reasonable definition of apply...)
def compose(*fns):
def composition(*args, **kwargs):
return reduce((lambda computed, next_fn: next_fn.apply(computed)),
fns,
(args, kwargs))
return composition
# define fns as above without decorator
hogof = compose(f, g, h)
- francoisdevlin 16y agoTo expand on what I was thinking with #8, here's how I'd implement a decorator in Clojure (def my-decor (partial comp decor-bevior)) Done.
- leif 16y agoWell, what python calls a "decorator" is just a function that accepts a function and returns a function with roughly similar functionality. In python, the old way to decorate functions was def my_decorator(f): ... def my_function(...): ... my_function = my_decorator(my_function) and the new "@my_decorator" syntax is just sugar for this. Function composition is only one of many things you can do with decorators. You could implement a K-combinator with them if you wanted to: def kestrel(x): "decorates a function to evaluate that function, but then return x" def decorator(f): def g(*args, **kwargs): f(*args, **kwargs) return x return g return decorator @kestrel(4) def foo(x): y = x + 1 print y return y foo(5) # => 4, but prints 6