[plt-scheme] srfi-42, values, named let, etc.
On 9/22/07, Jens Axel Søgaard <jensaxel at soegaard.net> wrote:
> Hi David,
>
> > Is there some way of modifying it so that it plays nice with
> > :parallel? Alternatively, is there some way of modifying :parallel so
> > that it plays nice with the above ?
>
> Tough questions. My first thought is that the problem might be
> rooted in the definition of :parallel :
>
> (:parallel <generator>*)
> Runs several generators in parallel. This means that the next
> binding in the sequence is obtained by advancing each generator in
> <generator>* by one step. The parallel generator terminates when any
> of its component generators terminates. The generators share a common
> scope for the variables they introduce. This implies that the names of
> the variables introduced by the various generators must be distinct.
>
> The part that troubles me is the: "The generators share a common
> scope for the variables they introduce."
>
> If I recall correctly, my first implementation gave each generator
> its own scope. Whether it was accident or whether I just thought
> it was the most natural, I don't remember.
>
> In fact the following test exposes whether or not the introduced
> variables share scope
>
> (my-check
> (list-ec (:parallel (:integers x)
> (:do ((i 10)) (< x i) ((- i 1))))
> (list x i))
> => '((0 10) (1 9) (2 8) (3 7) (4 6)) )
>
> This relates to your G) which asked why the following
> expressions didn't return the same result:
>
> (let ([a 1][b 1])
> (zip
> (list-ec (:do ((a 0)) (< a 10) ((+ a b))) a)
> (list-ec (:do ((b 0)) (< b 10) ((+ a b))) b)))
>
> (let ([a 1][b 1])
> (list-ec (:parallel
> (:do ((a 0)) (< a 10) ((+ a b)))
> (:do ((b 0)) (< b 10) ((+ a b)))) (list a b)))
>
> [NB: The last expressions crashes DrScheme, if no memory limit is set!]
>
Sorry, I thought that it would just run forever, as the call to the
named let is a tail call. Is DrScheme keeping extra information?
> It seems to me that both types of :parallel (with and without shared
> scope of introduced variables) are useful. If normal naming were used,
> they ought to be called :parallel (separate scope) and :parallel-rec
> (shared scope), but since the one with shared scope is named :parallel
> in SRFI42, we need another name. In lieu of a better name I'll
> call it :parallel-sep.
I suspect that the reason for the semantics of :parallel is that it
would be difficult to write it any other way using just syntax-rules.
>
> The definition of :parallel is given by the following - the
> interesting clause is the one with two generators:
>
> (define-generator (:parallel form-stx)
> ; TODO: Check that all subforms are generators
> (syntax-case form-stx (index)
> [(_ (index i) q ...)
> (add-index form-stx #'(_ q ...) #'i)]
> [(_ gen)
> (generator->loop #'gen)]
> [(_ gen1 gen2)
> (syntax-case (list (loop-stx (generator->loop #'gen1))
> (loop-stx (generator->loop #'gen2))) ()
> [(((ob ...) (oc ...) (lb ...) ne1
> (ib ...) (ic ...) ne2 (ls ...))
> ((ob2 ...) (oc2 ...) (lb2 ...) ne12
> (ib2 ...) (ic2 ...) ne22 (ls2 ...)))
> (make-loop
> #'((ob ... ob2 ...)
> (oc ... oc2 ...) (lb ... lb2 ...)
> (and ne1 ne12) (ib ... ib2 ...)
> (ic ... ic2 ...) (and ne2 ne22)
> (ls ... ls2 ...)))])]
> [(_ gen1 gen2 gen3 ...)
> #'(:parallel (:parallel gen1 gen2) gen3 ...)]))
>
> As can be seen the outer bindings (ob ...) and (ob2 ...)
> are merged into (ob ... ob2 ...) which means that get to
> share scope.
>
> To define a :parallel-sep we can introduce a marker,
> and use it to mark everything that stem from the
> second generator. One way to introduce a new mark
> is to use make-syntax-introducer to make a syntax-marker
> with a fresh mark.
>
> Are you interested in giving it a go?
>
I'll try. My ability to confuse myself with macros is seemigly limitless.
> --
> Jens Axel Søgaard
>
>
>