Goroutines in Lisp

Based on your input, here’s the translated Go code example into Lisp, formatted in Markdown suitable for Hugo.


A goroutine is a lightweight thread of execution.

(defun f (from)
  (dotimes (i 3)
    (format t "~a : ~a~%" from i)))

(defun main ()
  ;; Synchronous function call
  (f "direct")

  ;; Asynchronous function call using a thread
  (bt:make-thread (lambda () (f "goroutine")))

  ;; Asynchronous anonymous function call
  (bt:make-thread (lambda ()
                     (format t "going~%")))

  ;; Waiting to ensure all threads finish execution
  (sleep 1)
  (format t "done~%"))

(main)

Suppose we have a function call f where from is a string. Here’s how we’d call that in the usual way, running it synchronously.

(f "direct")

To invoke this function in a thread, we use bt:make-thread. This new thread will execute concurrently with the calling one.

(bt:make-thread (lambda () (f "goroutine")))

You can also start a thread for an anonymous function call.

(bt:make-thread (lambda ()
                   (format t "going~%")))

Our two function calls are running asynchronously in separate threads now. We wait for them to finish (for a more robust approach, you might use a synchronization primitive like semaphores or locks).

(sleep 1)
(format t "done~%")

When we run this program, we see the output of the blocking call first, then the output of the two threads. The threads’ output may be interleaved because threads are being run concurrently by the Lisp runtime.

$ lisp-interpreter your-program.lisp
direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2
done

Next we’ll look at a complement to threads in concurrent Lisp programs: channels.