Skip to content
Jason E. Aten edited this page Jan 10, 2016 · 57 revisions

zygomys is a dialect of LISP. It is designed as an embedded extension language for Go. It is implemented in pure Go as a bytecode interpreter. As a result, the interpreter can be compiled or cross-compiled for any platform Go runs on.

The zygo library REPL can easily be used either standalone or embedded as a library in your Go application. This facilitates creating an interactive command-line for your application.

Differences from traditional LISP syntax

  • ^ replaces `

In macros, templates (syntax-quotes) are introduced by the caret ^ instead of the backtick. This allows the convenient use of the backtick to delimit verbatim, newline and double quote containing strings, just as in Go.

So instead of this:

(defmac require [sympath]
    `(source (sym2str (quote ~sympath)))) ; not supported

Do this instead:

(defmac require [sympath]
    ^(source (sym2str (quote ~sympath)))) ; way better!
  • Raw string literals using a pair of backticks

Just as in Go, you may submit strings like this:

> (def a `hello
 readable
 "quotes"`)
> a
"hello\n readable\n\ "quotes\""
>
  • defmap to create records.

The defmap macro defines a new record type that is a hash table with a new name. Field definition order is always preserved upon display.

> (defmap ranch)
> (def lazy8 (ranch cowboy:"Jim" cowgirl:"Jane"))
> lazy8
(ranch cowboy:"Jim" cowgirl:"Jane")
>
  • clojure like field access with the ':' colon operator

Instead of writing (hget acre100 :friend), instead there is the briefer (:friend acre100)

> (defmap wood)
> (def acre100 (wood tractor:"Bessie" combine:"Steve" friend:"Eeyore"))
> (assert (== (:friend acre100) "Eeyore"))
>
  • clojure like threading with (-> hash field: field2: ...) for picking out nested fields. Note a difference from clojure however: the colon is always on the trailing (right) side of the symbol. Note that a space after the -> operator is required.
> (defmap ranch)
> (def hogwild (ranch cowboy:"Harry" cowgirl:"Hermonie"))
> (defmap bunkhouse)
> (hset! hogwild bunk1:(bunkhouse bed1:"Luciuos" bed2: "Dumbledore"))
> (defmap closet)
> (hset! (:bunk1 hogwild) closet1:(closet broom:"Nimbuz2"))
> (assert (== (-> hogwild bunk1: closet1: broom:) "Nimbuz2"))
> (assert (== (-> hogwild bunk1:closet1:broom:) "Nimbuz2"))
> hogwild
 (ranch cowboy:"Harry" cowgirl:"Hermonie" bunk1: (bunkhouse bed1:"Luciuos" bed2:"Dumbledore" closet1: (closet broom:"Nimbuz2")))
> 
  • == instead of = for equality checking.

Notice this in the repl snippet above. Its just less confusing to eyes accustomed to more common Go, C, etc. And we may wish to use '=' later for useful purposes.

  • Symbols can be invoked directly

Like scheme, in a function call, we evaluate the (1st) position just like all the other positions. The function position isn't special. This means if a symbol refers to a function's name, you can use that symbol in the first (function name) position, without fuss. No (funcall sym) needed as in lisp. There is a single namespace for all symbols.

> (def myprintsymbol 'printf)
> (myprintsymbol "in hex: %x\n" 32) ;; invokes printf
in hex: 20
>

See also this reference.

Clone this wiki locally