I can't think of an alternative to explicit state for this problem.

Probably we agree that your attempt didn't really "avoid mutation". It
was using mutation that's already present and exposed --- which is
often a good alternative to introducing more mutation, but maybe it
doesn't help much here, anyway.

At Fri, 7 Aug 2015 22:36:32 -0500, "Alexander D. Knauth" wrote:
> Oh, thanks!
> That makes sense.
> 
> On the off chance that you have an idea, is there a good way of doing this 
> that doesn't require b being able to see c?
> 
> On Aug 7, 2015, at 10:23 PM, Matthew Flatt <mfl...@cs.utah.edu> wrote:
> 
> > That's an interesting attempt to exploit the mutation inherent in a
> > recursive definition context to build a reference chain.
> > 
> > It doesn't work across module boundaries because the recursive binding
> > context doesn't extend across that boundary. The binding structure
> > created by your example is something like
> > 
> > (let ()
> >   (define (a) b)
> >   (define (b) c)
> >   (let ()
> >     (define (c) ....)
> >     ....))
> > 
> > Here, the body of `a` can refer to `b`, because they're in the same
> > recursive definition context. The body of `b` cannot refer to `c`,
> > however, because `c` is in a different context (although the body of
> > `c` can see `b`). An importing module is analogous to the more nested
> > context above.
> > 
> > 
> > The way you wrote the example, it may seem that `(add id b)` is somehow
> > able to reference the definition in `(add id c) `, but that's not the
> > case. The `(add id c)` is able to refer to things in "test1.rkt", and
> > it also prints itself, so '(a b c) show up together. Since the `(add id
> > b)` doesn't see `(add id c)`, the pieces that `(add id d)` can see
> > point back to the same identifier as when `(add id c)` traverses them,
> > so you end up with a duplicate definition of that identifier. That is,
> > the `next-next` identifier created by `(add id b)` is never bound in
> > the same was that `c` is never bound above for `(define (b) c)`.
> > 
> > 
> > At Fri, 7 Aug 2015 22:02:48 -0500, "Alexander D. Knauth" wrote:
> >> Hi. I have been trying to create a macro that communicates without using 
> >> mutation, but I'm having problems with communicating across multiple 
> modules.  
> >> 
> >> I have three files:
> >> 
> >> macro.rkt:
> >> #lang racket
> >> (provide start add)
> >> (require (for-syntax syntax/parse racket/match racket/syntax))
> >> (begin-for-syntax
> >>  ;; (thing stx-lst next-id)
> >>  ;; stx-lst : Syntax ; will be quoted
> >>  ;; next-id : Identifier ; points to the next identifier, which is or will 
> be 
> >> the next thing
> >>  ;;   if the next thing exists, then this one is old
> >>  (struct thing (stx-lst next-id) #:transparent)
> >>  ;; get-thing : Identifier -> thing
> >>  (define (get-thing id)
> >>    (follow-next-things (syntax-local-value id)))
> >>  ;; follow-next-things : thing -> thing
> >>  (define (follow-next-things v)
> >>    (match v
> >>      [(thing _ next-id)
> >>       (define v* (syntax-local-value (syntax-local-introduce next-id) (λ 
> >> () 
> >> #f)))
> >>       (cond [v* (follow-next-things v*)]
> >>             [else v])])))
> >> (define-syntax start
> >>  (syntax-parser
> >>    [(start id)
> >>     #:with next (generate-temporary #'id)
> >>     #'(define-syntax id (thing #'() #'next))]))
> >> (define-syntax add
> >>  (syntax-parser
> >>    [(add id new-stx)
> >>     #:do [(match-define (thing stx next-id) (get-thing #'id))]
> >>     #:with (old-stx ...) (syntax-local-introduce stx)
> >>     #:with next (syntax-local-introduce next-id)
> >>     #:with next-next (generate-temporary #'id)
> >>     (printf "macro.rkt add\n  next: ~v\n" #'next)
> >>     #'(begin
> >>         (define-syntax next (thing #'(old-stx ... new-stx) #'next-next))
> >>         '(old-stx ... new-stx))]))
> >> 
> >> test1.rkt:
> >> #lang racket
> >> (provide id)
> >> (require "macro.rkt")
> >> (start id)
> >> (add id a) ; '(a)
> >> (add id b) ; '(a b)
> >> 
> >> test2.rkt:
> >> #lang racket
> >> (require "macro.rkt" "test1.rkt")
> >> (add id c) ; this works fine, produces '(a b c) when run
> >> ;(add id d) ; module: duplicate definition for identifier
> >> 
> >> If I uncomment the last line of test2.rkt, it produces that duplicate 
> >> definition error.
> >> 
> >> I'm guessing that the second use of add in test2.rkt isn't picking up the 
> >> next-id definition put there by the first use of add in test2.rkt.
> >> 
> >> When I run test1.rkt in DrRacket it prints out:
> >> macro.rkt add
> >>  next: .#<syntax id1>
> >> macro.rkt add
> >>  next: .#<syntax id2>
> >> '(a)
> >> '(a b)
> >> 
> >> The first 4 lines were printed out by the add macro at compile time, and 
> the 
> >> last 2 are the run time results.
> >> 
> >> When I run test2.rkt in DrRacket it prints out:
> >> macro.rkt add
> >>  next: .#<syntax id3>
> >> '(a)
> >> '(a b)
> >> '(a b c)
> >> 
> >> But then if I uncomment the last line:
> >> macro.rkt add
> >>  next: .#<syntax id3>
> >> macro.rkt add
> >>  next: .#<syntax id3>
> >> module: duplicate definition for identifier in: id3
> >> With this at the bottom:
> >> module: duplicate definition for identifier at: id3 in: (define-syntaxes 
> (id3) 
> >> (thing (syntax (a b d)) (syntax id2)))
> >> 
> >> The message at the bottom shows that the (add id d) isn't picking up the 
> >> next-id definition put there by the (add id c), so that it puts out (a b 
> >> d) 
> >> instead of (a b c d), and tries to define the same next-id that the 
> previous 
> >> (add id c) already defined.
> >> 
> >> What's happening here?
> >> 
> >> I know about the separate compilation guarantee, but don't think that 
> >> could 
> be 
> >> the problem, since it works perfectly when add is used only once in 
> test2.rkt.
> >> 
> >> Alex Knauth
> >> 
> >> 
> >> -- 
> >> You received this message because you are subscribed to the Google Groups 
> >> "Racket Users" group.
> >> To unsubscribe from this group and stop receiving emails from it, send an 
> >> email to racket-users+unsubscr...@googlegroups.com.
> >> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to