tag:blogger.com,1999:blog-10770855.post115095130913035481..comments2024-03-28T03:20:57.393-04:00Comments on The Little Calculist: A semantics for propheciesDave Hermanhttp://www.blogger.com/profile/00405190527081772997noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-10770855.post-1151558963264499592006-06-29T01:29:00.000-04:002006-06-29T01:29:00.000-04:00dang; in the attempt to wrangle my comment into bl...dang; in the attempt to wrangle my comment into blogger, i lost a part: please mentally insert the following just after the first code citation in my previous comment:<BR/><BR/>---<BR/><BR/>this seems like a useful feature,<BR/>because with channels you'd have to<BR/>arrange for your own sentinel-passing<BR/>scheme to signal the end of data, and it<BR/>would be easy to screw up.<BR/><BR/>one funny thing about the implementation<BR/>is that, if you call<BR/><B>prophecy-next</B> after the yielded<BR/>values have been exhausted, you'll get a<BR/>stop-iteration exception, and then if<BR/>you call it <I>again</I> you'll just<BR/>hang (on async-channel-get). you<BR/>haven't specified yet what semantics you<BR/>want here, but it might be more<BR/>intuitive to always return the exception<BR/>(in the same way that a port returns the<BR/>end-of-file object forever).Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10770855.post-1151558078607328182006-06-29T01:14:00.000-04:002006-06-29T01:14:00.000-04:00ha, yes i guess we're on the same pagewith that on...ha, yes i guess we're on the same page<BR/>with that one.<BR/><BR/>in fact, though, the fullness of your<BR/>implementation explains why a "prophecy"<BR/>is not just a watered-down channel (as<BR/>it seemed to me at first).<BR/><BR/>in particular, you ensure that the<BR/>stream of values is terminated when the<BR/>prophecy code returns:<BR/><BR/>(define (build-prophecy thunk)<BR/> (let ([ch (make-async-channel)])<BR/> (make-prophecy ch (thread (lambda ()<BR/> (parameterize ([current-channel ch])<BR/> (dynamic-wind void thunk (lambda ()<BR/> (yield *done*)))))))))<BR/><BR/>next, note that in the case of non-local<BR/>control flow (perhaps a backtracking<BR/>algorithm is yielding the values? work<BR/>with me ...) you might end up calling<BR/><B>(yield *done*)</B> multiple times<BR/>via the dynamic-wind wrapper. it<BR/>appears that this won't effect the<BR/>behavior of <B>prophecy-next</B> in<BR/>the normal case -- multiple *done*<BR/>values won't confuse it. but it might<BR/>be cleaner to just do it once, like<BR/>this:<BR/><BR/>(define (build-prophecy thunk)<BR/> (let ([ch (make-async-channel)])<BR/> (make-prophecy ch (thread (lambda ()<BR/> (parameterize ([current-channel ch])<BR/> (thunk)<BR/> (yield *done*)))))))<BR/><BR/>of course, there's still the concern<BR/>about the case of the thunk not<BR/>returning directly, but rather<BR/>generating an exception.<BR/><BR/>in the current implementation, prophecy<BR/>code that produces an exception just<BR/>stops producing values, and<BR/><B>prophecy-next</B> will give the<BR/>stop-iteration exception. but is this<BR/>really a "safe" semantics? for example,<BR/>if we take at face-value the<BR/><B>prophecy->stream</B> of this<BR/>prophecy, we might get the wrong idea:<BR/><BR/>(prophecy<BR/> (set-exhaustion-alarm!)<BR/> (yield "the answer to life")<BR/> (yield "the universe")<BR/> (yield "and everything")<BR/> (yield "is ...")<BR/> (think)<BR/> (yield "forty")<BR/> (think) ;; alarm goes off here?<BR/> (yield "two"))<BR/><BR/>that is, we could get a truncated stream<BR/>of values without any way to know that<BR/>the prophet fell over mid-sentence.<BR/><BR/>of course, there is a similar problem<BR/>with asynchronous channels. but maybe<BR/>this is an opportunity for prophecies to<BR/>provide useful additional semantics.<BR/><BR/>what do you think of trying to propagate<BR/>exception information from the prophet<BR/>to the supplicant? you could wrap the<BR/>thunk in a handler that, upon catching<BR/>an exception, would pass the exception<BR/>message (say) along the channel in a way<BR/>that <B>prophecy-next</B> would<BR/>understand that it should not return a<BR/>normal value, nor raise the<BR/>stop-iteration exception, but rather<BR/>raise a dead-prophet exception<BR/>containing the prophet's dying words?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10770855.post-1150999063336504722006-06-22T13:57:00.000-04:002006-06-22T13:57:00.000-04:00That is hilarious -- you've just exactly reverse e...That is hilarious -- you've just <I>exactly</I> reverse engineered my implementation! Download the <A HREF="http://planet.plt-scheme.org/#prophecy.plt1.0" REL="nofollow">PLaneT package</A> and check out the source code. :DDave Hermanhttps://www.blogger.com/profile/00405190527081772997noreply@blogger.comtag:blogger.com,1999:blog-10770855.post-1150996910677093052006-06-22T13:21:00.000-04:002006-06-22T13:21:00.000-04:00if i understand correctly, the prophecy mechanism ...if i understand correctly, the prophecy mechanism is a way to produce an arbitrary number of values in a non-blocking way, and make those values available for another thread to collect in FIFO order.<BR/><BR/>(and then you use the delay and force primitives via the stream abstraction to give the consuming thread a nice way to treat this stream of values as a datastructure.)<BR/><BR/>(the prophecy-next might have to block if the producing thread hasn't yet yielded more values, right?)<BR/><BR/>anyway, i think the prophecy semantics are quite similar to that of an infinitely-buffered, asynchronous "channel". for example, using mzscheme's "Buffered Asynchronous Channels" library, it seems that you could implement prophecies like this:<BR/><BR/>(define current-prophecy-channel (make-parameter #f))<BR/><BR/>(define (yield v) <BR/> (async-channel-put (current-prophecy-channel) v))<BR/><BR/>(define (prophecy-next p)<BR/> (async-channel-get p))<BR/><BR/>(define (prophecy thunk)<BR/> (let ([prophecy-channel (make-async-channel #f)])<BR/> (parameterize ([current-prophecy-channel prophecy-channel])<BR/> (thread thunk))<BR/> prophecy-channel))<BR/><BR/>(i've left "prophecy" as a function that takes a thunk for simplicity, but a quick macro would give the look you specify.)<BR/><BR/>with a unique "stop-iteration" value it would be straightforward to write prophecy->stream from prophecy-next.Anonymousnoreply@blogger.com