Their argument [0] against namedtuple is that the namedtuple implementation is basically a hackier macro anyway (format a string then eval it). But I agree that it's not the most impressive example of what you can do with macros (see my other post).
Some of these things look really nice. I'm particularly impressed by the tracing macro:
with trace:
sum = 0
for i in range(0, 5):
sum = sum + 5
prints
sum = 0
for i in range(0, 5):
sum = sum + 5
range(0, 5) -> [0, 1, 2, 3, 4]
sum = sum + 5
sum + 5 -> 5
sum = sum + 5
sum + 5 -> 10
sum = sum + 5
sum + 5 -> 15
sum = sum + 5
sum + 5 -> 20
sum = sum + 5
sum + 5 -> 25
This would save a huge amount of boring typing `print(...)` when debugging,
and since it's only for debugging you don't even need to have MacroPy as a
dependency!
Unfortunately python 3.4 support is not quite ready [0], and attempting to
install it with `pip3` just fails.
It seems nice, but not quite as powerful. I like the way the tracing macro automatically prints every intermediate value, but q doesn't seem to do that.
I'm a little confused where you are going with this. Could you elaborate a little? Its one thing for this to be possible using `coding`, but this is a macro builder available right now. Interpy just highlights the possibility of this, right? If there were a macro framework that used `coding` it would seem more relevant. Otherwise it looks like you're comparing apples and a knife. Am I missing something?
Combined with this, we can make Meteorjs-like applications in Python directly. Even AST transformation of backend DOM operations in Python directly rendered to Javascript to browser.
It works in or out of the REPL (in fact, they document "MacroPy also works in the REPL"). It's just standard-ish in Python documentation to give examples formatted the way the REPL would display them.
Looks like a fun project on its own, with a lot of syntax tree hackery going on, but I see no real (pragmatic) use since many of the AST hacks and use cases presented are in my opinion completely unwarranted and can already be solved by the existing machinery (perhaps with quite heavy use of the metaclasses).
As an example, instead of hacking the AST via macros:
@case
Point(x, y): pass
one could just do a (this example implies, of course, that there is a CaseClassMeta somewhere attached to CaseClass):
class Point(CaseClass):
fields = 'x', 'y'
Not only this is nicer, you retain full control of the MRO on the metaclass level and can adjust its behaviour as needed and when needed.
Enums, complex enums and class body nesting examples -- can also be solved via metaclasses quite easily.
Quick lambdas example -- is somewhat close to "whatever" Python library, this is probably the one case which cannot be reproduced as is without AST hacks.
And one could use complex, or quaternions to represent points in order to not have to reinvent the wheels of rotation/translation/computing area/projections/polar to cartesian ...
I think the class point is the proof OOP is not able to give a real use case for itself other than reimplementing the wheel poorly.
OOP has proven to be confusing the youngs and lazy. It makes people confused about abstraction and the concrete world (map and territory).
It is pedantic, and inefficient.
EDIT: But the code of this guy is still amazing, even if totally pushing in wrong directions sometimes: memoization is the worst caching strategy possible. On the other hand the PEG parser is brilliant, like most of the code.
Yes, the use of macros is not always justified in the examples, because Python is quite expressive already.
However, the ability to have macros is orthogonal with the feature set of the language. What is interesting is the ability to inspect and modify a Python AST.
Of course, meta-programming is a way to integrate otherwise absent features of a language as-if they were built-in.
Python is sufficiently dynamic that most things can be done using existing facilities, like reflection and metaobjects (the @case example, as you mention).
But there is a difference between using those facilites at runtime and producing some code at macro-expansion time (this might be relevant for Cython, for example).
You can, for example, define a domain-specific language that is directly translated as Python, and not interpreted like an API-based representation would. You can even apply custom type checking for that DSL.
Or, you could analyze an existing python source code and produce a translation in another language without having to reimplement a parser (see the Python-to-Javascript example, or Common-Lisp's Parenscript).
18 comments
[ 3.0 ms ] story [ 57.4 ms ] thread[0]: https://github.com/lihaoyi/macropy#skeletons-in-the-closet
Unfortunately python 3.4 support is not quite ready [0], and attempting to install it with `pip3` just fails.
[0]: https://github.com/lihaoyi/macropy/issues/32
https://pypi.python.org/pypi/q
"import q; q(var1, var2)" forces printing to $TMPDIR/q (usually /tmp/q) very detailed output of what you are tracing and what it is.
The @q decorator does somewhat the same as the "with trace" context manager.
https://github.com/syrusakbary/interpy
previously https://news.ycombinator.com/item?id=9340784
Does JSX-like template for Python count?
https://github.com/dropbox/pyxl
Combined with this, we can make Meteorjs-like applications in Python directly. Even AST transformation of backend DOM operations in Python directly rendered to Javascript to browser.As an example, instead of hacking the AST via macros:
one could just do a (this example implies, of course, that there is a CaseClassMeta somewhere attached to CaseClass): Not only this is nicer, you retain full control of the MRO on the metaclass level and can adjust its behaviour as needed and when needed.Enums, complex enums and class body nesting examples -- can also be solved via metaclasses quite easily.
Quick lambdas example -- is somewhat close to "whatever" Python library, this is probably the one case which cannot be reproduced as is without AST hacks.
https://pypi.python.org/pypi/whatever
Here is my sokal version of class point; just repr overload for complex: https://gist.github.com/jul/9286835
I think the class point is the proof OOP is not able to give a real use case for itself other than reimplementing the wheel poorly.
OOP has proven to be confusing the youngs and lazy. It makes people confused about abstraction and the concrete world (map and territory).
It is pedantic, and inefficient.
EDIT: But the code of this guy is still amazing, even if totally pushing in wrong directions sometimes: memoization is the worst caching strategy possible. On the other hand the PEG parser is brilliant, like most of the code.
However, the ability to have macros is orthogonal with the feature set of the language. What is interesting is the ability to inspect and modify a Python AST.
Of course, meta-programming is a way to integrate otherwise absent features of a language as-if they were built-in. Python is sufficiently dynamic that most things can be done using existing facilities, like reflection and metaobjects (the @case example, as you mention).
But there is a difference between using those facilites at runtime and producing some code at macro-expansion time (this might be relevant for Cython, for example).
You can, for example, define a domain-specific language that is directly translated as Python, and not interpreted like an API-based representation would. You can even apply custom type checking for that DSL.
Or, you could analyze an existing python source code and produce a translation in another language without having to reimplement a parser (see the Python-to-Javascript example, or Common-Lisp's Parenscript).