A dialect of Lisp extended to support concurrent programming.
LispEx is another Lisp Interpreter implemented with Go. The syntax, semantics and library procedures are a subset of R5RS:
LispEx 0.1.0 (Saturday, 19-Jul-14 12:52:45 CST)
;; lambda expression
>>> ((lambda (x y . z) (+ x y (car z))) 1 2 5 11)
8
;; currying
>>> (define (curry func arg1) (lambda (arg) (apply func arg1 (list arg))))
>>> (map (curry + 2) '(1 2 3 4))
(3 4 5 6)
;; apply
>>> (apply + 1 2 '(3 4))
10
;; composite function
>>> (define ((compose f g) x) (f (g x)))
>>> (define caar (compose car car))
>>> (caar '((1 2) 3 4))
1
;; tail recursion 
>>> (letrec 
      ((even? (lambda (n) (if (= 0 n) #t (odd? (- n 1)))))
       (odd?  (lambda (n) (if (= 0 n) #f (even? (- n 1))))))
      (even? 88))
#t
;; multiple nestings of quasiquote 
;; (challenging to have a right implementation)
>>> `(1 `,(+ 1 ,(+ 2 3)) 4)
(1 `,(+ 1 5) 4)
>>> `(1 ```,,@,,@(list (+ 1 2)) 4)
(1 ```,,@,3 4)
;; lazy evaluation
>>> (define f (delay (+ 1)))
>>> (force f)
1What's new, the Go-like concurrency features are introduced in LispEx. You can start new coroutines with go statements, and use <-chan or chan<- connecting them. A ping-pong example is shown below:
; define channels
(define ping-chan (make-chan))
(define pong-chan (make-chan))
; define a buffered channel
(define sem (make-chan 2))
(define (ping n)
  (if (> n 0)
    (begin
      (display (<-chan ping-chan))
      (newline)
      (chan<- pong-chan 'pong)
      (ping (- n 1)))
    (chan<- sem 'exit-ping)))
(define (pong n)
  (if (> n 0)
    (begin
      (chan<- ping-chan 'ping)
      (display (<-chan pong-chan))
      (newline)
      (pong (- n 1)))
    (chan<- sem 'exit-pong)))
(go (ping 6))  ; start ping-routine
(go (pong 6))  ; start pong-routine
; implement semaphore with channel, waiting for ping-pong finishing
(<-chan sem) (newline)
(<-chan sem) (newline)
; should close channels if you don't need it
(close-chan sem)
(close-chan pong-chan)
(close-chan ping-chan)
; the output will be: ping pong ping pong ... exit-ping exit-pongFurthermore, select statement is also supported, which is necessary for you to select between multiple channels that working with concurrent routines. Just like Go, the code can be written like this:
(define chan-1 (make-chan))
(define chan-2 (make-chan))
(go (chan<- chan-1 'hello-chan-1))
(go (chan<- chan-2 'hello-chan-2))
(select
  ((<-chan chan-1))
  ((<-chan chan-2))
  (default 'hello-default))
(close-chan chan-1)
(close-chan chan-2)
; the output will be: hello-default, as it will cost some CPU times when a coroutine is lanuched.In this scenario, default case is chosen since there is no ready data in chan-1 or chan-2 when select statement is intepretered. But such scenario will be changed if we sleep the main thread for a while:
(define chan-1 (make-chan))
(define chan-2 (make-chan))
(go (chan<- chan-1 'hello-chan-1))
(go (chan<- chan-2 'hello-chan-2))
; sleep for 20 millisecond
(sleep 20)
(select
  ((<-chan chan-1))
  ((<-chan chan-2))
  (default 'hello-default))
(close-chan chan-1)
(close-chan chan-2)
; the output will be randomized: hello-chan-1 or hello-chan-2For more interesting examples, please see files under tests folder.
- Clean designed code, very easy for you to understand the principle, inspired from yin
 - A concurrent design for lexical scanning, inspired from Rob Pike
 - Builtin routines, channels and other necessary components for concurrent programming
 - Give you a REPL
 
loopin R5RS- tail call optimization
 - type checker
 
git clone https://github.com/kedebug/LispEx.git
cd LispEx
go build && ./LispEx
LispEx 0.1.0 (Saturday, 19-Jul-14 12:52:45 CST)
>>> 
From here you can type in forms and you'll get the evaluated expressions back. To interpreter a file:
./LispEx filename.ss
Lisp is fun, go is fun, concurrency is fun. Hope you will have an extraordinary programming experience with LispEx.
MIT