[Python-ideas] History on proposals for Macros?
Ron Adam
ron3200 at gmail.com
Sun Mar 29 19:21:00 CEST 2015
On 03/28/2015 09:51 PM, Steven D'Aprano wrote:
> But we might be able to rescue this proposal by dropping the requirement
> that the compiler knows when to pass the syntax tree and when to
> evaluate it. Suppose instead we had a lightweight syntax for generating
> the AST plus grabbing the current context:
>
> x = 23
> spam(x + 1, !(x+1)) # macro syntax !( ... )
>
>
> Now the programmer is responsible for deciding when to use an AST and
> when to evaluate it, not the compiler, and "macros" become regular
> functions which just happen to expect an AST as their argument.
Something related to this that I've wanted to experiment with, but is hard
to do in python to be able to split a function signature and body, and be
able to use them independently. (But in a well defined way.)
A signature object could have a default body that returns the closure.
And a body (or code) could have a default signature that *takes* a namespace.
Then a function becomes ...
code(sig(...)) <---> function(...)
The separate parts could be created with a decorator.
@signature
def sig_x(x): pass
@code
def inc_x(): x += 1
@code
def dec_x(): x -= 1
In most cases it's best to think of applying code bodies to names spaces.
names = sig_x(0)
inc_x(names)
dec_x(names)
That is nicer than continuations as each code block is a well defined unit
that executes to completion and doesn't require suspending the frame.
(Yes, it can be done with dictionaries, but that wouldn't give the macro
like functionality (see below) this would. And there may be other benifits
to having it at a lower more efficient level.)
To allow macro like ability a code block needs to be executable in the
current scope. That can be done just by doing...
code(locals()) # Dependable?
And sugar to do that could be...
if x < 10:
^^ inc_x #just an example syntax.
else:
^^ dec_x # Note the ^^ looks like the M in Macro. ;-)
Possibly the decorators could be used with lambda directly to get inline
functionality.
code(lambda : x + 1)
And a bit of sugar to shorten the common uses if needed.
spam(x + 1, code(lambda : x + 1))
spam(x + 1, ^^: x + 1)
Cheers,
Ron
More information about the Python-ideas
mailing list