

Parens - parens is a scripting layer for Golang that uses lisp syntax
source link: https://www.tuicool.com/articles/hit/ZVbQRfb
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Parens
Parens is a LISP-like scripting layer for Go
(or Golang
).
Installation
To embed parens in your application import github.com/spy16/parens
.
For stand-alone usage, install the parens binary using:
go get -u -v github.com/spy16/parens/cmd/parens
Then you can
- Run
REPL
by runningparens
command. - Run a lisp file using
parens <filename>
command. - Execute a LISP string using
parens -e "(+ 1 2)"
Usage
Take a look at cmd/parens/main.go
for a good example.
Check out examples/
for supported constructs.
Goals:
1. Simple
Should have absolute bare minimum functionality.
scope := reflection.NewScope(nil) exec := parens.New(scope) exec.Execute("10")
Above snippet gives you an interpreter that understands literals, (eval expr)
and (load <file>)
.
2. Flexible
Should be possible to control what is available. Standard functions should be registered not built-in.
stdlib.RegisterAll(scope)
Adding this one line into the previous snippet allows you to include some minimal set of standard functions like +
, -
, *
, /
etc. and macros like let
, cond
, do
etc.
The type of scope
argument in parens.New(scope)
is the following interface:
// Scope is responsible for managing bindings. type Scope interface { Get(name string) (interface{}, error) Bind(name string, v interface{}) error Root() Scope }
So, if you wanted to do some dynamic resolution during Get(name)
(e.g. If you wanted to return method Print
of object stdout
when Get("stdout.Print")
is called), you can easily implement this interface and pass it to parens.New
.
3. Interoperable
Should be able to expose Go values inside LISP and vice versa without custom signatures.
// any Go value can be exposed to interpreter as shown here: scope.Bind("π", 3.1412) scope.Bind("banner", "Hello from Parens!") // functions can be bound directly. // variadic functions are supported too. scope.Bind("println", fmt.Println) scope.Bind("printf", fmt.Printf) scope.Bind("sin", math.Sin) // once bound you can use them just as easily: exec.Execute("(println banner)") exec.Execute(`(printf "value of π is = %f" π)`)
4. Extensible Semantics
Special constructs like do
, cond
, if
etc. can be added using Macros.
// This is standard implementation of '(do expr*)' special-form from Clojure! func doMacro(scope *reflection.Scope, callName string, exps []parser.Expr) (interface{}, error) { var val interface{} var err error for _, exp := range exps { val, err = exp.Eval(scope) if err != nil { return nil, err } } return val, nil } // register the macro func in the scope. scope.Bind("do", parser.MacroFunc(doMacro)) // finally use it! src := ` (do (println "Hello from parens") (label π 3.1412)) ` // value of 'val' after below statement should be 3.1412 val, _ := exec.Execute(src)
See stdlib/macros.go
for some built-in macros.
Parens is NOT :
- An implementaion of a particular LISP dialect (like scheme, common-lisp etc.)
- A new dialect of LISP
TODO
- Better way to map error returns from Go functios to LISP
-
Result<interface{}, error>
type of design in Rust ?
-
- Better
parser
package- Support for macro functions
- Support for vectors
[]
- Better error reporting
- Better
reflection
package- Support for variadic functions
- Support for methods
- Type promotion/conversion
-
intX
types toint64
andfloat64
-
floatX
types toint64
andfloat64
- any values to
interface{}
type -
intX
andfloatX
types toint8
,int16
,float32
and vice versa?
-
- Performance Benchmark (optimization ?)
-
Go
code generation?
Recommend
-
132
Brigade: Event-Driven Scripting for Kubernetes Brigade is a full-featured, event-driven scripting platform built on top of Kubernetes. It integrates with many different event sources, more are always being added, and it's easy to create y...
-
103
Neugram Neugram is a scripting language and shell. It is an early-stage experimental hobby project. You can install from HEAD with: go get -u neugram.io/ng The language uses Go's syntax fo...
-
80
Smartparens Table of Contents Smartparens is a minor mode for dealing with pairs in Emacs. It can automatically insert pairs: wrap, unwrap and rewrap pairs: expand and contract pairs: ...
-
81
kscript - Having fun with Kotlin scripting Enhanced scripting support for Kotlin on *nix-based systems. Kotlin has some built-in support for scripting already but it is not yet...
-
10
Calling Python Methods - Subtleties with and without Parens Oct 28, 2019 Photo courtesy of my boss and...
-
10
Cherry picking commits & shell scripting in golang Yesterday I was talking about Kubernetes! One interesting thing about working with Kubernetes is that it forces me to think more about Google’s internal devel...
-
7
Copy link Contributor
-
7
Prig: like AWK, but uses Go for “scripting” February 2022 Summary: The article describes Prig, my AWK-like tool that uses Go as the scripting language. I compare Prig with AWK, then dive into how Prig works, an...
-
9
proposal: Go 2: Lightweight anonymous function syntax #21498
-
2
shaunlebron/history-of-lisp-parens master
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK