multithreadingscopecommon-lispdynamic-scope

WITH-OUTPUT-TO-STRING with multithreading in Common Lisp


I want to do something that means the following:

(with-output-to-string (*standard-output*)
  (bt:join-thread
   (bt:make-thread
    (lambda ()
      (format *standard-output* "Hello World")))))
;=> "" (actual output)
;=> "Hello World" (expected output)

In my understanding, this does not work because the *standard-output* that gets dynamically rebound by with-output-to-string outside the thread does not take effect inside the thread. What are the possible and recommedable ways?

In essence, I want to capture the output that was written to *standard-output* by another thread.


Solution

  • One can rebind the special variable to be thread local:

    (with-output-to-string (*standard-output*)
      (bt:join-thread
        (bt:make-thread
          (lambda ()
            (format *standard-output* "Hello World"))
          :initial-bindings `((*standard-output* . ,*standard-output*)))))
    

    *initial-bindings* is an alist with (variable . value) elements.