Comments (12)
I remember thinking I might need weird lambda calculus tricks to implement a yield
macro. I thought about continuation-passing style and call/cc
. Still not sure if that's doable. However, Ensue
might make that unnecessary.
The full injection is not quite as bad as I made it sound. If a tree-walker could recognize the if-else
, it could avoid expanding it before processing its subexpressions, which is basically how it would work as a special form. Each special form has to be special cased in the walker. That's why having only two of them makes writing code walkers a lot easier. All other (non-string injecting) macros could be macroexpanded to make them expressible in terms of these.
I feel like string-injection macros might be a common problem that walkers can't be expected to anticipate. They might kind of work like the "compiler macros" of Common Lisp (which are not the same thing as "macros"). Maybe if there were a standard way to mark these (an expand-after
macro?) or a way to choose between an injected or non-injected implementation (an *inject*
var?) then this could be made to work better.
from hissp.
I'm tempted to just do this. The inject-body version, I mean. But it's going to break a lot of examples in the docs, which would be a pain. I feel like I should finish the current doc project before I begin another one. Unlike a full injection, which would probably require a redo of all affected examples, I could probably just do a find and replace. Maybe it won't be that bad.
from hissp.
Looks like not that bad. Undoing it would be harder, but maybe still possible with a regex find-and-replace.
from hissp.
Looks like I can do @
lists and #
sets just as easily.
There are a number of other macros that could benefit from this treatment, but they're more complicated. The best way to do %
dicts is probably to create a dict literal in the body with string manipulation. The unpacking makes it tricky, but it's doable. &&
and ||
would be trivial if they were strictly binary. Making them multiary recursively like they are now wouldn't realize as much benefit as creating an inline helper function of the proper arity. Same with cond
, which would just be a multiary if-else
. when
and unless
would get a little bit simpler, since the nil case would not have to be passed in.
I feel like I implemented an injected throw
before I found the walk_tb
. Deserves another look if I can find it.
from hissp.
It was in the wiki here https://github.com/gilch/hissp/wiki/Bundled-macro-candidates#raise
.#"(x for x in'')"
, to make the generator, but it still needs to be closed. Could wrap in a doto
. Longer injectables could close it too.
(g:=(x for x in'')).close()or g # Leaks g.
(lambda g=(x for x in''):g.close()or g)() # Doesn't, but longer.
Leaking is really not OK even with a gensym. (Although Hy did it a lot, last I checked.) The alternative is pretty much a doto
, so I may as well doto
.
from hissp.
doto
doesn't auto-wrap like ->
. Must have missed that. Fixed in feature branch. ensue
is implemented in terms of ->
, so should be fine. Were there any others?
from hissp.
when
and unless
were fairly easy fixes, but they break a lot of examples and can't be fixed with a simple regex find-and-replace, since their arity changed. I just have to go through all the examples.
%
, &&
, ||
, and cond
will need to compute a helper string to inject because it will depend on arity. These are going to be the most difficult. Their examples are going to change too, and not in a way I can fix with a regex. I'll probably have to redo all of them.
from hissp.
when
/unless
are done. The rest will have to wait for tomorrow, at least.
from hissp.
&&
and ||
are done. Not as easy, but not really harder than writing a normal macro. Implementing one made the other pretty obvious.
cond
may be slightly more difficult. %
will probably be the hardest. The unpacking makes it tricky.
from hissp.
cond
was harder, but doable given the &&
and ||
. The old recursive macro definition in terms of if-else
was really quite a bit simpler.
An optimization for these branching macros occurred to me. Any literal expressions need not be thunkified to delay evaluation. That's only required for evaluable forms (tuples and strings, and not the strings containing literals). However, this means that the body must avoid calling them like thunks as well, but still call anything thunkified. Matching these up would complicate the macros, although I suppose it's doable with enough code. if-else
, when
, and unless
might be better defined in terms of cond
in that case. It's not clear if &&
and ||
should be.
That just leaves %
, which seems at least as difficult as cond
was.
Given this technique, I'm wondering if there are any additional Python expressions I would want macros for. Generator expressions/comprehensions perhaps, but I don't see this working any better than the itertools and builtins. I'll have to look over that wiki page.
from hissp.
%
is done. It was about as hard as cond
.
I can't say that I should have done them this way in the first place. The old non-injecting implementations were worth writing for dogfooding purposes. The dynamic string-manipulation ones are fairly complex. Their expansions are a lot less noisy, but their implementations are a lot more difficult to understand. These would have been hard to write without the macro suite in place. I'm not sure this was an improvement. This feels like bloat. I'm tempted to just make them binary (or binary-recursive), but that wouldn't work for %
.
from hissp.
Because it's a bit cryptic, I also wanted to mention somewhere that the X+1&-2
in cond
is so that an odd number of arguments will crash (it ensures the helper always has an even number of parameters). cond
is defined pretty early and I didn't have throw
available yet.
from hissp.
Related Issues (20)
- Parsing quirks HOT 9
- Inclusion criteria HOT 14
- Rethink FAQ HOT 2
- clojure macros?
- 0.4 release HOT 7
- macroexpansion could be easier
- Rethink reader macros HOT 2
- Write a debugger macro walkthrough.
- Rethink ->> HOT 7
- Rethink `!` and `#""` HOT 12
- Handle qualified names in `attach`
- Stricter left-to-right evaluation order HOT 2
- `deftype` should be able to take `kwds`
- one time donations problem, please try receive some crypto as donation, maybe nano cryptocurrency
- Consider inject literals in Lissp (raw symbols) HOT 3
- Gensysms aren't good enough HOT 4
- Build broke on Python 3.11
- Synexpand may be too sensitive HOT 1
- & doesn't factor well in synexpand HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hissp.