
Show HN: Runiq, a little Lisp-inspired language that runs on JavaScript - matthewtoast
https://github.com/matthewtoast/runiq
======
matthewtoast
Runiq is my attempt to tie together a few ideas from Lisp with some features
of JavaScript inside an interpreted language. Syntax, flexibility, data-as-
code DNA would come from Lisp, while a JS backing could give reach and a big
module ecosystem.

Runiq more or less does this translation:

    
    
        source: (hack (the) (planet!))
        ast: ["hack", ["the"], ["planet!"]]
        reduce order: "the" "planet!" -> "hack"
    

Function tokens map to predefined CPS JavaScript functions:

    
    
        "hack": function(a,b,cb){...}, // add numbers
        "the": function(cb){...}, // return 1
        "planet!": function(cb){...}, // return 2
    

Outputs produce new trees that eventually reduce to a value.

    
    
        -> ["hack", ["the"], ["planet!"]]
        -> ["hack", 1, 2]
        -> [3]
        -> 3
    

Runiq is very much an experiment, and some design decisions I made have trade-
offs (speed, for one). But Runiq could still find a niche somewhere between
grown-up projects like Clojure(Script) and single-purpose languages like
PuzzleScript, both of which I admire.

------
ktt
Cool! Reminds me of
[https://github.com/kanaka/miniMAL](https://github.com/kanaka/miniMAL)

~~~
matthewtoast
Very cool. It's amazing to me that the developer got it under 1KB.

This is the first I've heard of that project, but based on a quick skim, I can
point out a few differences between it and Runiq - although the two are
certainly similar in that they execute over a very simple plain-array-based
AST. (Clearly miniMAL and Runiq were created with different ultimate aims in
mind, so any fair comparison ends there. :) )

\- Runiq is fully designed around async. (At first glance I'm unsure how you
would express, say, an HTTP request or file I/O in miniMAL - i.e., anything
which in JS would require a callback.) In Runiq it would look something like
this:

    
    
        ; assuming 'print' and 'read-file' are defined in the DSL... ;
        (print (read-file "foo.txt"))
    

\- Runiq execution happens in parallel (taking a cue from functional
languages) and the tree can be reduced stepwise; Runiq has a built-in
mechanism for pause and resume. It looks like miniMAL executes wholesale, but
I may be mistaken.

\- Runiq has no (built-in) JavaScript interop, although it would be trivial to
add that feature via Runiq's DSL-building API. I specifically avoided adding
any type of sytnax to talk to JS _directly_ because I wanted Runiq to be a
safe sandbox by default, with the option to add "dangerous" functions easily
if need be.

But, that's super cool and I wish I'd come across that earlier!

