Unix シェル的なバックグラウンドでのタスク処理

bash> command &

みたいに、バックグラウンドで関数を呼び出して、値が必要になった時に表に戻す、というイディオムを思い付きました。

(define (& t)
  (let ((c (make-channel)))
    (thread
     (lambda ()
       (channel-put c (t))))
    (lambda (k)
      (k (channel-get c)))))

使い方

(let ((%
       (& (lambda () some hard work))))
  ...
  (% values))

ごちゃごちゃしがちなスレッドの同期処理がスッキリ書けて良いと思います。


追記:

lambda が面倒なので、マクロにしてみました:

(define-syntax &
  (syntax-rules ()
    ((& e)
     (let ((c (make-channel)))
       (thread (lambda () (channel-put c e)))
       (lambda (k) (k (channel-get c)))))
    ((& e1 e2 ...)
     ;; Concurrent version of `begin'
     (let ((l (list (& e1) (& e2) ...)))
       (lambda (k)
         (let loop ((l l))
           ((car l)
            (lambda (v)
              (if (null? (cdr l))
                  (k v)
                  (loop (cdr l)))))))))))

式が複数有る場合、それぞれをスレッド下で処理するようにしています。begin と同様に、最後の式の値だけ得られるようになってます。