-
Notifications
You must be signed in to change notification settings - Fork 81
Home
zygomys is a dialect of LISP, but one that contains significant built-in infix syntax support, making it exceptionally easy to read. 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.
When you don't want script to read/write the filesystem or issue system calls, you can sandbox it.
Start the repl with zygo -sandbox
. (See also the -quiet
flag).
When embedding use the NewGlispSandbox()
method in place of NewGlisp()
.
- Using
=
for assignment and multiple assignment
The =
sign represents assignment. To support Go-like multiple assignment, the =
assignment operator supports multiple values on either side of the =
sign. After the following assignment,
(a b c = 1 "two" 3)
a
will be 1, b
will be "two", and c
will be 3.
- Using dot-symbols for nested member selection
Dot-symbols act like path descriptors for referencing nested objects.
Like Go/C++/Java, dot-symbols let one easily pick out members of nested objects:
zygo> // make an nested object
zygo> (def sn (snoopy asst: (hornet forecast: (weather desc:"sunny"))))
(snoopy asst: (hornet forecast: (weather desc:"sunny")))
zygo> sn.asst
(hornet forecast: (weather desc:"sunny"))
zygo> sn.asst.forecast
(weather desc:"sunny")
zygo> sn.asst.forecast.desc
"sunny"
zygo>
- Minor syntax improvement: ^ 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"))
>
> // or using dot-symbol syntax
> acre100.friend
`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. The newer dot-symbol syntax now offers the same functionality with even more compact notation. Both are retained as one may be easier to generate programmatically.
> (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 use '=' for assignment.
- 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.