About two months ago, in my ongoing project to make a
quasiquote operation that allows users to define their own variants of
unquote as macros, I hit a snag. I took some time away from the problem for a couple of months, but lately I’ve come back to pick up where I left off, and the extensible
quasiquote now has a complete implementation. (Here’s the relevant Git commit.) It doesn’t do anything out of the box that other
quasiquote implementations don’t do, but it uses hypersnippets to do it, and as planned, it allows users to define their own alternatives to
To get past the snag I hit, I thought I would need to implement several “selective” operations on hypertees. It turns out I only needed one:
hypertee-zip-selective. This operation makes it possible to zip two hypertees while selectively skipping some of the holes of each one. This makes it easy to store data in some hypertee holes while still treating others as actual holes, which is useful for representing hypersnippet-shaped data besides hypertees themselves.
So, now I have a working implementation of a quasiquotation operator with user-definable
unquote. I should really write a better post at some point describing how this technique works. In order to get to something that’s simple and stable enough to write useful guide materials for, I’m planning to focus next on cleaning up some of the mess I’ve made trying to implement it over the past couple of years.
I pulled out my ordinal code from Lathe Morphisms into its own library, Lathe Ordinals. It’s like a lot of ordinal number libraries out there already. This Maple documentation is a pretty thorough, if terse, description of the kind of thing I’m implementing for Racket.
This is another journal entry of my progress toward an extensible quasiquotation syntax. It wanders a bit, but I think it has a happy ending. :)
My last post was about “higher quasiquotation.” Since then, I’ve taken to calling that subject hypersnippets, since the characteristic feature is that it’s a repeated iteration of the concept of “the snippet of code between this boundary and this boundary.” Degree-N hypersnippets are made up of all the code in between a degree-(N-1) hypersnippet shape and zero or more nonoverlapping degree-(N-1) hypersnippet shapes appearing inside it. A degree-1 hypersnippet is like a text selection, and degree-0 hypersnippet is a text stream. Quotation is a certain kind of DSL where the syntax is hypersnippet-shaped, but there are potentially other uses for these shapes.
(Spoilers: Yesterday I finally convinced myself hypersnippet shapes were precisely the opetopes, and hypersnippet-shaped data is data that’s composable using the operations of an opetopic ω-category. So hypersnippets in my original sense are an ω-category generated by some free 1-cells corresponding to characters that can appear in a text stream. (Update 6-3-2018: Michael Arntzenius points out that these generators on their own would just generate strings. I was also sloppy about specifying the generator cells’ sources and targets here. Looks like I need one generator of each opetopic shape to be the holes, with each one’s sources and target being lower-dimensional holes; as well as one generator corresponding to each text character, each of which is a 2-cell with no sources, targeting the unique 1-cell hole.) Nevertheless, I’m still going to refer to these as “hypersnippets” in this post, and I think it’s valuable to refer to them by their intended usage domain in case they morph into a slightly different concept, even if the concept now seems to have stabilized into something that corresponds with opetopes.)
I call it Cairntaker. It’s for programmers who want well-tended heaps.
During this time, the potential value of static type systems has become quite clear to me. For the most part I still really don’t care about protecting programmers from their own mistakes. Instead what I value is the ability to make promises about program behavior that untrusting parties can verify on their own (for non-hackish metaprogramming and secure code distribution), the ability to write expressive abstractions that don’t sacrifice any run-time performance, and the ability to infer a program’s implementation from its interface. I still like the dynamic programming ideal of putting lots of power in the programmer’s hands… but whence else comes this power? Rather than stubbornly reinventing the existing static type research under some other name, I embrace it.
I haven’t felt the pain of the asynchronous callback nesting problem firsthand, but I know a horror close to that one: Monadic programming in Groovy. Observe the indentation.
In fact, that indentation-heavy part of the Blade code is what originally got me fed up with using Groovy and interested in making Penknife as an intermediate project on the way to Blade. Well, my work on Penknife has been so focused on modularity and hygiene that it’s slack on what really matters: Syntax. Oh, syntax, how you really really matter so! :-p
$ cd /path/to/jarc
$ java -server -cp \
> "jarc.jar;$GROOVY_HOME/embeddable/groovy-all-1.7.2.jar" jarc.Jarc
Jarc> (= lathe-dir* "path/to/lathe/arc/")
Jarc> (load:+ lathe-dir* "loadfirst.arc")
Jarc> (use-rels-as jv (+ lathe-dir* "imp/jvm.arc"))
#3(tagged mac #<procedure>)
Jarc> (jv.jvm!groovy-util-Eval-me "2 + 2")
It’s on now.
After about a month of me submitting bugs to the Arc forum and Jarc’s creator, JD Brennan, fixing them, Jarc is now compatible enough with Arc 3.1 that my Lathe (the library I introduced last time) now wholeheartedly supports the Jarc implementation of Arc. This means it works on four Arc setups: Jarc, official Arc 3.1 (which itself needs a Windows fix), Anarki (which needs the same fix), and Rainbow. Most of you reading this are probably from the Arc forum, in which case you knew all that already. :-p
Those are all the setups I want Lathe to support for now, but I might consider arc3f, arc2c, or another Arc implementation if I realize it’s actually active. Another complication is that quite a lot of Arc users modify one of the PLT Scheme versions of Arc (Arc or Anarki) to suit their needs. In those cases, I figure the burden of Lathe compatibility is on them if they need it.
Still, there is a bit of a need to add new features to Arc. To this end, Anarki, Jarc, and Rainbow have provided ways to call from Arc into the host platform (PLT Scheme, the JVM, and the JVM respectively).