-
Notifications
You must be signed in to change notification settings - Fork 2
Home
uehaj edited this page Sep 13, 2010
·
44 revisions
Welcome to the LispBuilder wiki!
LispBuilder is lisp interpreter and parser implemented as Groovy’s Builder. LispBuilder accepts Lisp like expression, and can be evaluated on groovy.
def bx = new LispBuilder() assert bx.build{progn ${defun; fib; ${n} ${IF; ${or; ${equal; n; $1}; ${equal; n; $2}} $1 ${add; ${fib; ${add; n; $(-1)}} ${fib; ${add; n; $(-2)}}}}} ${fib; $10} }.eval() == 55
def env = new Env() env.eval{progn ${defun; improve; ${y; x} ${average; y; ${div; x; y}}} ${defun; good_enoughp; ${y; x} ${le; ${abs; ${sub; ${mul; y; y}; x}}; $(0.000001)}} ${defun; sqrt_iter; ${y; x} ${IF; ${good_enoughp; y; x} y ${sqrt_iter; ${improve; y; x} x}}} ${defun; sqrt; ${x} ${sqrt_iter; $(1.0); x}}} assert env.eval{sqrt; $(3.0)} == 1.73205081
The lisp code needs to obey the following rules as Groovy DSL.
- Use dollar sign ‘$’ and curly bracket ‘{}’ instead of round brackets.
Usual Lisp | LispBuilder |
---|---|
(a) | ${a} |
- Elements in list are delimited by semicolons (‘;’).
Usual Lisp | LispBuilder |
---|---|
(a b c) | ${a;b;c} |
- The semicolons before newline can be omitted.
Usual Lisp | LispBuilder |
---|---|
(a b c) |
${a b c} |
- Dollar sign is applied to the string atom.
Usual Lisp | LispBuilder |
---|---|
“ABC” | $“ABC” |
- Dollar sign is applied also to the nonnegative integer atom.
Usual Lisp | LispBuilder |
---|---|
123 | $123 |
- Other numeric constants are bundled with dollar sign and round brackets.
Usual Lisp | LispBuilder |
---|---|
-3 | $(-3) |
1.25 | $(1.25) |
- Use capital letters for the reserved words of Groovy.
Usual Lisp | LispBuilder |
---|---|
if | IF |
true | TRUE |
false | FALSE |
- Use add,sub,mul,div instead of +,-,*,/.
Usual Lisp | LispBuilder |
---|---|
(+ a b) | ${add; a; b} |
(- a b) | ${sub; a; b} |
(* a b) | ${mul; a; b} |
(/ a b) | ${div; a; b} |
- The symbol that has same name of Groovy/Java class name collides. For example, ‘fib’ cannot be used as a symbol with groovy code ‘fib.groovy’. Because symbol ‘fib’ is treated as the class name.
Making the display color of ‘$’ and ‘;’ to faint by syntax highlight setting may help readability :)
The semantics of this Lisp is comparatively traditional with dynamic scope, but the following points are different.
- FALSE and nil is different.
- No special quote (’) notation (use (quote ..)).
- No #’ notation.
- No macros.
- No implicit progn in body of lambda.
- Case sensitive.
List of built-in functions and predefined functions is shown as follows(see Functions.groovy in detail).
Built-in functions | eq IF quote TRUE FALSE nil car cdr cons setq and or progn equal lt le gt ge add sub mul div defun call print println |
Predefineds function | not neq nullp append |
- Arbitrary Groovy and Java code can be called from lisp (see sample/swing.groovy).
- Lazy evaluation like that in functional language. If Groovy closure is in list element, the evaluated value is the result of closure, and the closure is replaced to the value when that is called first time. See fibonacci.groovy. You can implement infinite length list.
def zip(a,b) { new Cons(a.car+b.car, {zip(a.cdr, b.cdr)}); } fibs = new Cons(0, new Cons(1, {zip(fibs, fibs.cdr)})) assert fibs[34] == 5702887
- LispBuilder2 & 3. those are other implementations of lisp parser.(see sample/fibonacci2.groovy, sample/fibonacci3.groovy)
assert bx.build{$($(progn, $(defun, fib, $(n), $(IF, $(or, $(equal, n, 1), $(equal, n, 2)), 1, $(add, $(fib, $(add, n, -1)), $(fib, $(add, n, -2))))), $(fib, 10))) }.eval() == 55
assert bx.build{[[progn, [defun, fib, [n], [IF, [or, [equal, n, 1], [equal, n, 2]], 1, [add, [fib, [add, n, -1]], [fib, [add, n, -2]]]]], [fib, 10]]] }.eval() == 55