
Quick examples...
Note that parenthesis always mean a function call or native lisp form, and function calls always use outer-parentheses.
Traditional lisp style:
// tail recursion; tail-call optimization works, so this won't overflow the stack.
zygo> (defn factTc [n accum]
(cond (== n 0) accum
(let [newn (- n 1)
newaccum (* accum n)]
(factTc newn newaccum))))
zygo> (factTc 11 1) // compute factorial of 11, aka 11! aka 11*10*9*8*7*6*5*4*3*2
(factTc 11 1)
39916800
zygo>
An optional infix syntax is layered on top. The infix syntax is a subset of Go. Anything inside curly braces is infix. Outer parenthesis are still always used for function calls. The zygo REPL is in infix mode by default to facilitate math.
// show off the infix parser
zygo> x := 3; y := 5; if x + y == 8 { (println "we add up") } else { (println "wat?" ) }
we add up
zygo>
zygomys is an embeddable scripting language. It is a modernized Lisp with an object-oriented flavor, and provides an interpreter and REPL (Read-Eval-Print-Loop; that is, it comes with a command line interactive interface).
zygomys allows you to create a Domain Specific Language to drive your program with minimal fuss and maximum convenience.
It is written in Go and plays nicely with Go programs and Go structs, using reflection to instantiate trees of Go structs from the scripted configuration. These data structures are native Go, and Go methods will run on them at compiled-Go speed.
Because it speaks JSON and Msgpack fluently, zygomys is ideally suited for driving complex configurations and providing projects with a domain specific language customized to your problem domain.
The example snippets in the tests/*.zy provide many examples. The full documentation can be found in the Wiki. zygomys blends traditional and new. While the s-expression syntax defines a Lisp, zygomys borrows some syntax from Clojure, and some (notably the for-loop style) directly from the Go/C tradition.
The standalone REPL is called simply zygo. zygo is also shorthand
for the whole project when speaking aloud. In writing, the full
zygomys is used to aid searchability.
$ git clone https://github.com/glycerine/zygomys
# make: read git version and bakes it into zygo. Then runs all tests.
$ cd zygomys && make
tests/declare.zy for examples.(a.b.c.Fly) calls method Fly on object c that lives within objects a and b.zygo to configure trees of Go structs, and then run methods on them at natively-compiled speed (since you are calling into Go code).zygo -sandbox and see the NewGlispSandbox() function.emacs/zygo.el emacs mode provides one-keypress stepping through code.(range key value hash_or_array (body)) range loops act like Go for-range loops: iterate through hashes or arrays.(for [(initializer) (test) (advance)] (body)) for-loops match those in C and Go. Both (break) and (continue) are available for additional loop control, and can be labeled to break out of nested loops.(raw string) lets you do zero-copy []byte manipulation.(defmap) make configuration a breeze.(source "path-string").`backticks`, can contain newlines and " double quotes directly. Easy templating.repl/random.go, repl/regexp.go, and repl/time.go files for examples.(-> hash field1: field2:) and (:field hash) selection. {} curly braces. Expressions typed at the REPL are assumed to be infix (wrapped in {} implicitly), enhancing the REPL experience for dealing with math.
/*block*/ and //through end-of-line.+, -, *, /, mod, **)sll, srl, sra)bitAnd, bitOr, bitXor)<, >, <=, >=, ==, !=)and and or)cond)fn)def, defn, let, letseq)(macexpand (yourMacro)) makes writing/debugging macros easier.^() instead of backtick.% (not '; which delimits runes as in Go).See the wiki for lots of details and a full description of the zygomys language..
zygomys is a contraction of Zygogeomys, a genus of pocket gophers. The Michoacan pocket gopher (Zygogeomys trichopus) finds its natural habitat in high-altitude forests.
The term is also descriptive. The stem zygo comes from the Greek for yoke, indicating a pair or a union of two things, and mys comes from the Greek for mouse. The union of Go and Lisp in a small cute package, that is zygomys.
https://github.com/metacurrency/holochain
Two-clause BSD, see LICENSE file.
Jason E. Aten, Ph.D.
The ancestor dialect, Glisp, was designed and implemented by Howard Mao.
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/) The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: https://blog.golang.org/gopher
XKCD https://xkcd.com/297/ licensed under a Creative Commons Attribution-NonCommercial 2.5 License(https://xkcd.com/license.html).
In this latest version v9, I have replaced the background parsing goroutine with an iterator, holding the resumable parsing state on a coroutine stack rather than a background goroutine stack.
Let's measure the performance difference, if any:
On Go version go1.24.1 darwin/amd64:
Benchmark with a background goroutines keeping parsing state, zygomys v8.1.0, parsing a 5MB json file into memory. The average of 10 runs is shown.
$ git checkout v8.1.0
zygo> (timeit (fn [] (echo false) (source "5MB.json")) 10)
(timeit (fn [] (echo false) (source "5MB.json")) 10)
ran 10 iterations in 18.414136 seconds
average 1.841414 seconds per run
zygo>
Versus: benchmark the new version that uses an iterator (implicit coroutine) to hold parsing state, in v9.0.4:
$ git checkout v9.0.4
zygo> (timeit (fn [] (echo false) (source "5MB.json")) 10)
(timeit (fn [] (echo false) (source "5MB.json")) 10)
ran 10 iterations in 18.485201 seconds
average 1.848520 seconds per run
zygo> {1.848520 - 1.841414}/1.841414
0.003858990971068882
Conclusion: it is only 0.3% slower using an iterator (coroutine) instead of a background goroutine, and this allowed me to eliminate a mutex and five channels from the parser implementation.
And, on Linux, I see the coroutine version actually being 12% faster on go1.23.5 and go1.24.1.
I call it a win for more re-usable zygomys library code either way.
$ claude mcp add zygomys \
-- python -m otcore.mcp_server <graph>