Hacker News new | ask | show | jobs
by jgw 3694 days ago
Sure, s/built/are building/g.

Without going into too much detail, I basically am subsuming another language (statically-typed, Algol-ish) wholesale into Common Lisp. It replaces that language's syntax with an s-expression syntax, but also provides a way to embed its native syntax. So you can use CL macros to build syntactic abstractions, and use them as low-ceremony wrapping around native code. It also makes many of the primitives of that language into first-class objects in Lisp, so a REPL for the embedded language is emerging (or expressed another way, you can evaluate the embedded language in the CL REPL). I don't think Clojure would do as good a job (gut feeling; I'm not a Clojurist). Racket would probably be a decent choice, but not sure if I'd get good performance (again, not a Schemer).

One of the more arrogant things I've heard Lispers claim of their language is "a superset of all other languages". While that's not entirely true, this work has made me feel that there's more than a kernel of truth in that hyperbole. Warts and all! :)

2 comments

That's pretty amazing. What sort of tools and features did you use to do that? Genuinely interested as CL is a language I always keep in the back of my mind for the "next project" and this is giving me a big push to use it.
Programmable syntax (reader macros), programmable printer are 2 big ones. Also regular macros are key, manipulating code as structures not text, having both lexical and dynamic variables, closures and all the other nuts and bolts stuff. Type and compiler-optimization declarations help keeping things fast (well, not fast enough, but I'm trying!)
Thank you :)

I think you were correct about Clojure. I read recently reader macros are not an available feature.

Yes, mostly. reader macros are not extensible by the user. The compiler has and uses reader macros.

Rich Hickey has said he hasn't seen an implementation of reader macros that is compose-able across libraries. i.e. two different OSS libs using a two different incompatible macros.

If I understand well, you wrote/are writing a macro that parses your algol-ish language, so you can do, if your language is java, something like:

    (let ((my-java-class  
           (java public class MyClass {
                   public MyClass() {}
                   public myMethod() {System.out.println("hello");}
                  })))
          (myMethod (my-java-class)))
And it shows on the REPL:

     hello
That's quite impressive, and I can see how it opens new horizons.
Bit late replying to this, so I hope you see it, but as I noted elsewhere, the key here is something called a "reader macro". This is a mechanism by which you can control the behaviour of the Lisp reader (i.e., the READ function), and occurs before regular macroexpansion. I use [] to denote s-expressions in the embedded-language domain, and {} to introduce native syntax, which passes its contents through to an actual parser - which returns s-expressions. I can print the resulting forms in native syntax, embedded-s-expressions, or plain Lisp. It's a neat demonstration of the superficiality of syntax.

Perhaps another interesting observation is that what I'm building today is not actually what I originally set out to do, which was more limited in scope. Perhaps another weakness of CL is its tendency to seduce you into feature-creepism. :)