On 10/19/2011 11:39 AM, Neil Toronto wrote:
On 10/19/2011 10:31 AM, John Clements wrote:

On Oct 19, 2011, at 9:29 AM, John Clements wrote:


On Oct 19, 2011, at 4:03 AM, Robby Findler wrote:

(I'm sorry if you got this message already; I thought I sent it
already but I don't see it.)

What about the current-output/error-port? what about the
current-namespace? current-custodian?

There are lots of parameters that affect core functions in subtle ways
and if you do something like this in plot, it seems like it could lead
to serious confusion someday. Also, it can introduce leaks.

+1. I think this is not not not a good idea.

Robby's solution requires you to make one list of all of the
plot-related parameters, which looks to me like the "right" amount of
work.

Furthermore, it has the unpleasant characteristic that when it
breaks, it will be exposed in an unwanted change to a parameter that
will likely be entirely unrelated to plot. Tracking this down will be
horrible, and the axe-wielding murderer of legend will be very
unhappy when he (or she?) finally gets to your doorstep.

Dangling pronoun. Of course, I meant to say

"Furthermore, [your solution] has the unpleasant characteristic..."

Look, as long as it's not Richard Stallman with the ax...

If I spawn a render thread that inherits the parent thread's parameters,
won't things like current-namespace and current-custodian have the right
values?

It's starting to look like that is the solution that is the most
maintainable and the least work. And it still allows users to
parameterize the functions they plot. If something breaks, it's not my
fault, because spawning a thread that waits on a channel for a "draw
now!" command, and then draws on a dc, should just work, right?

(There shouldn't be any contention over the dc because I'd have the
slideshow thread wait on an "all finished" reply over the channel.)

For concreteness, here's what I've got now:

;; f : any -> any
;; Returns a wrapper for 'f' that preserves most of the parameter values
;; in the dynamic extent where 'parameterize-procedure' is applied.
(define (parameterize-procedure f)
  (struct apply-thread (channel thread) #:transparent)
  (struct apply-command (kws kw-values rest) #:transparent)
  (struct exception-response (exception) #:transparent)
  (struct values-response (values) #:transparent)
  ;; A synchronous channel for commands and responses
  (define ch (make-channel))
  ;; The command loop
  (define (command-loop)
    (match-define (apply-command kws kw-values rest) (channel-get ch))
    (with-handlers ([(λ (e) #t)
                     (λ (e) (channel-put ch (exception-response e)))])
      (channel-put ch (call-with-values
                       (λ () (keyword-apply f kws kw-values rest))
                       (λ vals (values-response vals)))))
    (command-loop))
  ;; Save the thread in a struct so it'll get closed over
  (define th (apply-thread ch (thread command-loop)))
  ;; Return the wrapper
  (make-keyword-procedure
   (lambda (kws kw-args . rest)
     (match-define (apply-thread ch _) th)
     (channel-put ch (apply-command kws kw-args rest))
     (match (channel-get ch)
       [(exception-response e)  (raise e)]
       [(values-response vals)  (apply values vals)]))))

I can't decide whether it's ugly or beautiful. It works great, though.

Neil T
_________________________________________________
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/users

Reply via email to