Greetings loafers! (ฮป-gophers haha, get it?)
This is a bytecode compiler and VM for a language closely resembling Clojure, a Clojure dialect, if you will.
Here are some nebulous goals in no particular order:
- Quality entertainment,
- Making it legal to write Clojure at your Go dayjob,
- Implement as much of Clojure as possible - including persistent data types and true concurrency,
- Provide comfy two-way interop for arbitrary functions and types,
- AOT (let-go -> standalone binary) would be nice eventually,
- Strech goal: let-go bytecode -> Go translation.
Here are the non goals:
- Stellar performance (cough cough, it seems to be faster than Joker),
- Being a drop-in replacement for clojure/clojure at any point,
- Being a linter/formatter/tooling for Clojure in general.
It can eval a Clojure-like lisp. It's semi-good for solving Advent of Code problems but not for anything more serious yet.
There are some goodies:
- Macros with syntax quote,
- Reader conditionals,
- Destructuring,
- Multi-arity functions,
- Atoms, channels & go-blocks a'la
core.async
, - Regular expressions (the Go flavor),
- Simple
json
,http
andos
namespaces, - Many functions ported from
clojure.core
, - REPL with syntax-highlighting and completions,
- Simple nREPL server that seems to work with BetterThanTomorrow/calva,
I'm currently contemplating:
- Dynamic variables,
- Exceptions & more comprehensive runtime errors,
- Numeric tower i.e. floats, bignums and other exotic number species,
- Optimized persistent data-structures and laziness,
- Records and protocols,
- A real test suite would be nice,
See:
- My AoC 2022 solutions for an idea of how let-go looks like,
- Examples for small programs I wrote on a whim,
- Tests for some random "tests".
Check out this bare-bones online REPL. It runs a WASM build of let-go in your browser!
Building or running let-go from source requires Go 1.19.
go install github.com/nooga/let-go@latest
Try it out:
let-go
The best way to play with let-go
right now is to clone this repo and run the REPL like this:
go run .
To run an expression:
go run . -e '(+ 1 1)'
To run a file:
go run . test/hello.lg
Use the -r
flag to run the REPL after the interpreter has finished with files and -e
:
go run . -r test/simple.lg # will run simple.lg first, then open up a REPL
go run . -r -e '(* fun 2)' test/simple.lg # will run simple.lg first, then (* fun 2) and REPL