Hacker News new | ask | show | jobs
by paultag 4598 days ago
Original author of hylang here - because lisp is homoiconic, you have real macros, not AST macros; although the distinction isn't exactly clear, it's nice to have them as first-class members of the language, and allow them to avoid caring about stmt vs expr internally.

Happy to answer questions.

2 comments

Can you clarify what you mean about "real" macros vs AST macros? The only obvious extension to normal AST-style macros I can think of is fexprs, which re-run the macro procedure on every invocation (rather than once at read/build/macroexpansion/whatever time).
Well, two things.

Firstly, AST visitors in Python (or whatever) are clunky and lots of code to do what you say. Hell, I think that it's borderline unpythonic.

You have to consider lots of things, such as whether or not you can put an stmt where you're inserting code, and write a lot of, frankly ugly, Python code to do it.

Hy macros (and really Lisp macros) that are first-class members of the language are nice, because they're a lot more clean to write.

In addition, since Hy does some nasty stuff under the hood to generate clean Python AST, you can do stuff like:

   (print (if true true flase))
(Ok, that's a lie, since it'll do "print True if True else False", but if that had a (do) around everything, it'd still work by mangling the expression - just too tired to write that example right now :) )

Fundamentally, a Hy macro IS an AST macro, just on the parsed and tokenized Hy code (which turns into AST), rather then fiddling with Python AST (which isn't even a stable interface).

That answer the question? :)

Yes. Thanks.
I disagree that homoiconicity is required. Racket is not homoiconic and its macros are pretty powerful (Template Haskell is probably a clearer example but is arguably less powerful). What do you lose by not making the syntax homoiconic? Also what is your definition of homoiconicity?
I thought Racket was homoiconic. You can turn executable code into a data structure by quoting it (e.g. (+ 1 2) is executable code, but '(+ 1 2) is a data structure.) Wikipedia thinks Racket is homoiconic FWIW [ http://en.wikipedia.org/wiki/Homoiconic ]
Racket does not use S-Expressions internally, it uses syntax objects which are not really the same. Furthermore it makes no sense to even ascribe one surface syntax to Racket since it's more than one language really. Also if you ask the main developers of Racket if it's homoiconic they would probably tell you that it's irrelevant (and they would be right). In fact I have this in my IRC logs, "<samth> homoiconicity is a meaningless term that tells you nothing about macros"
It's not meaningless, a lot of people (myself included) use it to talk about programs that can alter their own program in the data structures that they're good at moving around.

In Python, the AST approximates this. Perhaps I'm lax in usage, but I think there's a continuum of homoiconicity - some things (like C) have no language functionality to deal with their own source code. Other languages (like CL) are very good at this, since you write the language in it's own data structures. Other languages (like Python, or Racket) aren't homoiconic, but they approximate what makes homoiconicity special.

Are you saying this approximation makes for less powerful macros? If you are, I find that to be ridiculous, as Racket's macro system is way beyond other Lisps' macro systems.

The syntax objects hold more information about scopes, namespaces and the like than they would were they just datum(s?).