[plt-scheme] letrec and threads
On Mon, 19 Feb 2007, Dimitris Vyzovitis wrote:
> And now the less simple case that results in undefined values:
> (define sch (make-channel))
> (define spawner
> (thread
> (lambda ()
> (let lp ((thunk (channel-get sch)))
> (thread thunk)
> (lp (channel-get sch))))))
>
> (define (spawn thunk)
> (channel-put sch thunk))
ok, this is wrong. spawn evaluates to void. Let me fix it:
(require (lib "list.ss" "srfi" "1"))
(define sch (make-channel))
(define spawner
(thread
(lambda ()
(let lp ((pend null))
(apply sync
(handle-evt sch
(lambda (v)
(let ((ch (car v))
(thr (thread (cdr v))))
(lp (cons (cons ch thr) pend)))))
(map (lambda (e)
(handle-evt (channel-put-evt (car e) (cdr e))
(lambda (evt)
(lp (delete e pend eq?)))))
pend))))))
(define (spawn thunk)
(let ((ch (make-channel)))
(channel-put sch (cons ch thunk))
(channel-get ch)))
(define (oops)
(define (foo other ch)
(channel-put ch other))
(letrec ((ch1 (make-channel))
(ch2 (make-channel))
(foo1 (spawn (lambda () (foo foo2 ch1))))
(foo2 (spawn (lambda () (foo foo1 ch2)))))
(values (thread? (sync ch1)) (thread? (sync ch2)))))
And now we get:
> (oops)
#f
#t
I don't see this as a bug, it is to be expected with the standard
expansion of letrec to
(let (...
(foo1 #<undefined>)
(foo2 #<undefined>))
...
(set! foo1 (spawn ...))
(set! foo2 (spawn ...))
...)
But it is still an interesting case of undefined behavior in the
presence of threads...
-- vyzo