The method name you give to define/generic is interpreted in the context of the generic interface name you provide. So if you supply the name "free" inside a macro, that's the wrong context. That error goes away, as you found, if you pass "free" as an argument to def-free.
After that, you get the error "free-box: undefined" because the #:fast-defaults predicate is lifted to a definition that comes before the definition of the free-box method. I'll fix that by reordering the definitions; meanwhile you can fix that by just eta-expanding your use of "compose". Carl Eastlund On Fri, Aug 16, 2013 at 5:41 PM, Carl Eastlund <c...@ccs.neu.edu> wrote: > The method names are always going to be in the context of the generic > interface name. There's nowhere else they can come from. > > Carl Eastlund > > > On Fri, Aug 16, 2013 at 5:39 PM, J. Ian Johnson <i...@ccs.neu.edu> wrote: > >> WRT the struct abstraction, using syntax-local-introduce on >> #'gen:binds-variables seemed to do the trick, oddly. >> -Ian >> ----- Original Message ----- >> From: "Carl Eastlund" <c...@ccs.neu.edu> >> To: "J. Ian Johnson" <i...@ccs.neu.edu> >> Cc: "dev" <dev@racket-lang.org> >> Sent: Friday, August 16, 2013 5:23:33 PM GMT -05:00 US/Canada Eastern >> Subject: Re: [racket-dev] Generics scoping issues >> >> >> Okay, let me dig into this. The expansion of define/generic is an odd >> thing in the way it treats the method names; I'm not at all sure I've >> gotten it right, or that it's clear what "right" should even be. I'll get >> back to you shortly. >> >> >> >> Carl Eastlund >> >> >> On Fri, Aug 16, 2013 at 5:17 PM, J. Ian Johnson < i...@ccs.neu.edu > >> wrote: >> >> >> Re: problem 1 - ah yes I see. >> Problem 2: >> In the body of def-free: >> >> generic-problems.rkt:16:26: define/generic: free is not a method of >> generic interfaces gen:binds-variables >> at: free >> in: (define/generic gfree free) >> >> This compiles if I additionally supply def-free with free, but it doesn't >> run: >> free-box: undefined; >> cannot reference an identifier before its definition >> in module: "/home/ianj/projects/oaam/code/generic-problems.rkt" >> context...: >> /home/ianj/projects/oaam/code/generic-problems.rkt: [running body] >> >> Furthermore, if I abstract over the struct form so that #:methods >> gen:binds-variables is part of the macro expansion, even passing free to >> def-free won't work anymore: >> >> (define-syntax-rule (astruct name (fields ...) (methods ...)) >> (struct name exp (fields ...) #:transparent #:methods gen:binds-variables >> [methods ...])) >> >> (astruct avar (name) >> [(def-free e gfree free bound avar [(x) (if (x . ∈ . bound) ∅ (set x))])]) >> >> generic-problems.rkt:31:27: define/generic: free is not a method of >> generic interfaces gen:binds-variables >> at: free >> in: (define/generic gfree free) >> >> >> >> >> ----- Original Message ----- >> From: "Carl Eastlund" < c...@ccs.neu.edu > >> To: "J. Ian Johnson" < i...@ccs.neu.edu > >> Cc: "dev" < dev@racket-lang.org > >> Sent: Friday, August 16, 2013 4:50:53 PM GMT -05:00 US/Canada Eastern >> Subject: Re: [racket-dev] Generics scoping issues >> >> >> >> Problem 1 -- you have to use define/generic if you want to use the >> generic version of something in the context of a set of specific method >> implementations. That's by design. >> >> Problem 2 -- what error message or unexpected behavior are you getting? >> That should work, it sounds like a bug in define/generic if it's not >> working. >> >> >> >> Carl Eastlund >> >> >> On Fri, Aug 16, 2013 at 4:36 PM, J. Ian Johnson < i...@ccs.neu.edu > >> wrote: >> >> >> I'm starting to use generics, and me being myself, I wrote some macros to >> make writing method definitions easier. >> But, I'm seeing that #:methods seems to rebind method identifiers in a >> way that hygiene interferes with. >> >> I would expect to be allowed to do the following two things (problems >> annotated): >> >> (struct exp (label fvs-box)) ;; parent struct for all expressions >> (define-generics binds-variables >> [free-box binds-variables] >> [free binds-variables #:bound [bound]] >> #:fallbacks [(define (free e #:bound [bound ∅]) ∅) >> (define free-box exp-fvs-box)] >> #:fast-defaults ([(compose unbox free-box) >> (define (free e #:bound bound) (unbox (free-box e)))])) ;; problem 1: >> free-box not in scope >> >> (define-syntax-rule (def-free e gfree bound struct [(pats ...) rhss ...]) >> (begin >> (define/generic gfree free) ;; problem 2: since #:methods rebinds free, >> this is not in the scope one would expect with its definition in the >> define-generics form. >> (define (free e #:bound [bound ∅]) >> (match e [(struct _ fvs-box pats ...) >> (set-box! fvs-box >> (let () rhss ...))])))) >> >> (struct var exp (name) #:transparent >> #:methods gen:binds-variables >> [(def-free e gfree bound var [(x) (if (x . ∈ . bound) ∅ (set x))])]) >> >> I have workarounds thanks to stamourv, but they're unpleasant: >> Problem 1: define free in fast-defaults as an eta-expansion of a >> definition outside the define-generics form that does what you want. >> Problem 2: add free as a parameter to def-free, and pass free in at all >> uses of def-free. >> >> The first problem seems like more of a programming error than the use of >> the wrong tool. >> The second problem seems like generic method identifiers should be >> syntax-parameters, if they indeed need to be rebound in the rhs of the >> #:methods argument. >> >> Are these expectations unreasonable/against the design decisions for >> generics? >> Thanks, >> -Ian >> >> _________________________ >> Racket Developers list: >> http://lists.racket-lang.org/dev >> >> >> >> >> >
_________________________ Racket Developers list: http://lists.racket-lang.org/dev