Macros in Python? (PEP 310)
Alex Martelli
aleax at aleax.it
Sat Apr 12 06:18:04 EDT 2003
A. Lloyd Flanagan wrote:
...
> I think you are making this a lot harder than it needs to be.
> Remember that function definitions are first class objects in python:
>
> def y(a, b):
> " a simple function to do nothing significant
> return a + b
>
> _y = y #save defn. of y
>
> def x(a, b):
> # function to wrap stuff around y
> print "hi"
> c = _y(a, b)
> print "bye"
> return c
>
> y = x #rebind y so it looks identical to caller
This is special-purpose code wrapping a function y callable
with two arguments, and no other -- to me, it's like answering
a question such as "can I write a Python function to sum two
numbers" with the answer "sure, 23+190". It's not hard at all
to make a slightly umore general wrapper:
def xify(func):
def xified(*args, **kwds):
print "hi"
result = func(*args, **kwds)
print "bye"
return result
return xified
now,
y = xify(y)
gives you the special-case you hardcoded above, but the
(modest) generalization should be OK.
Why is this generalization still modest:
-- func must be coded as a function (no way to pass
xify anonymous blocks of inline code except with the
feeble Python lambda which only allows an expression)
-- the prefix and postfix that wrap func are hard-coded
-- the postfix doesn't happen if func raises an exception
rather than returning normally
Point 1 is just too hard to fix -- Python just doesn't like
treating anonymous blocks of code as first-class objects.
Point 2 is easy to ameliorate, and point 3 is trivial, e.g.:
def mkprint(something):
def print_(): print something
return print_
def wrapfunc(func, pre=mkprint("hi"), post=mkprint("bye")):
def wrapped(*args, **kwds):
pre()
try: return func(*args, **kwds)
finally: post()
return wrapped
If you do this sort of thing a lot you'll no doubt want
lots of little helpers such as
def curry_to_0(func, *args, **kwds):
def curried(): return func(*args, **kwds)
return curried
def curry_to_anyp(func, *args, **kwds):
def curried(**more): return func(*(args+more), **kwds)
return curried
etc, etc (or, many of the little helpers could be grouped
into one larger helper, probably a class rather than a
closure). But it's gonna be fussy, due to the inability
to pass anonymous blocks of inline code and the distinction
between expressions and statements.
Alex
More information about the Python-list
mailing list