[Python-ideas] History on proposals for Macros?

Andrew Barnert abarnert at yahoo.com
Mon Mar 30 22:54:54 CEST 2015


On Mar 30, 2015, at 11:55, Ron Adam <ron3200 at gmail.com> wrote:
> 
> On 03/30/2015 03:03 AM, Andrew Barnert wrote:

[snip]

> And the reason for bringing this idea up here was I think it could be used to implement the lite macro behaviour that was suggested with a bit of added syntax.
> 
> On the other hand it appears to me, that Python is going in the direction of making it easier to compile to C code.  More dynamic features may not be helpful in the long run.

I don't think this is true. There definitely isn't any momentum in that direction--shedskin and its two competitors are dead, while PyPy and numba are alive and kicking ass. And I don't think it's desirable, or that the core developers think it's desirable.

If you think Guido's and Jukka's static type annotations are a step in the direction of static compilation, read the two PEPs; that's very explicitly not a goal, at least in the near term. (And the impression I get from the list discussions is that Guido is skeptical that it will be in the long term, but he's willing to keep an open mind.)

Anyway, usually, macros are used to generate a few functions that are called many times, not to generate a whole lot of functions that are only called once, so they don't cause any problems for a decent tracing JIT.

>>> >It was an incomplete example.  It should have been...
>>> >
>>> >    add_1_to_x = code(lambda: x + 1)
>>> >
>>> >and then later you could use it in the same way as above.
>>> >
>>> >    x = ^^ add_1_to_x
>> OK, it sounds like what you're really looking for here is that code(spam) returns a function that's just like spam, but all of its variables (although you still have to work out what that means--remember that Python has already decided local vs. cell vs. global at compile time, before you even get to this code function) will use dynamic rather than lexical scoping. All of the other stuff seems to be irrelevant.
>> 
>> In fact, maybe it would be simpler to just do what Lisp does: explicitly
>> define individual_variables_ as dynamically scoped, effectively the same
>> way we can already define variables as global or nonlocal, instead of
>> compiling a function and then trying to turn some of its variables into
>> dynamic variables after the fact.
> 
> It's something to try, but if a code block needs boiler plate to work, or the function it's put in needs it, it really isn't go to be very nice.

I think I didn't explain this very well.

Take a step back. Instead of having functions whose variables are all lexically scoped, and blocks whose variables are all dynamically scoped, what if you had just one kind of function, but two kinds of variables? Exactly like defvar in Lisp (although hopefully with a better name...). 

That's obviously more flexible. And it should be much simpler to implement. (And it's dead simple to fake in standard CPython 3.4, without hacking anything--as Steven pointed out, ChainMap makes it even easier).

Once you have dynamic variables, it's not that hard to add a new defblock statement that acts just like def except its variables are dynamic by default, instead of lexical.

That skips over all the problems with your first version and immediately gets you your second version, and it avoids most of the problems there as well. The only thing you're missing in the end is the ability to convert functions to blocks and vice-versa at runtime. That's the part that causes all the problems, and I don't think is actually necessary for what you want (but if I'm wrong, I guess never mind :).


More information about the Python-ideas mailing list