gilch / hissp

It's Python with a Lissp.
https://gitter.im/hissp-lang/community
Apache License 2.0
364 stars 9 forks source link

New composition macro #220

Closed gilch closed 1 year ago

gilch commented 1 year ago

Experimental. Unstable. Getting better! See also #218.

Renamed the# to my#. Breaking change if you were using that. Added nil#. It's one of those questionable, but maybe too-useful-to-omit macros I've been wanting for a while. Not sure if I'll keep it.

Probably nobody else is doing this yet, but I also broke Sybil tests with a modification to the compiler. Direct recursive macros no longer repeat the same expansion comment, but just keep a tally with an additional #.

The new composition macro (going with "synexpand") just does compile-time rewrites. There's no longer a run-time stack. I considered just composing functions at read time, which would have worked pretty well, but doing everything at compile time comes out even cleaner. And what's more, macros often work as terms in the mini-language and I kind of get apply for free. We could have almost gotten this much using normal-order function application with the composed function approach, which requires memoization for efficient evaluation, but that's too hard to shoehorn that into Python's pervasive mutability. Even a lot of the builtins return mutable iterators. Not as nice as Clojure's seqs. Python 2 was nicer in some ways.

PACK no longer requires a MARK. It will use the entire stack if there's no MARK to stop it short of that. Because they can now be unbalanced, I've changed them to <> instead of []. Because this creates a tuple at compile time, it can be used as an apply. If you just want the data itself, you can put `@ in the head to make it a list or quote it with quote:<.

The syntax expands directly to expressions, but common use cases would want a function. Like most macros, you can convert to a function by wrapping in a lambda, although this still can't use anything only knowable at run time (including, perhaps, the number of arguments, making variadic functions a problem). The easiest way would be to use X# and friends, but this still requires you to spell out the points, when most of the point of this was to be point-free. So I added helpers ^#, ^^#, ^^^#, and ^^^^# for arities 1-4.