<div dir="ltr"><div><div></div>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 &quot;free&quot; inside a macro, that&#39;s the wrong context.  That error goes away, as you found, if you pass &quot;free&quot; as an argument to def-free.<br>

<br></div>After that, you get the error &quot;free-box: undefined&quot; because the #:fast-defaults predicate is lifted to a definition that comes before the definition of the free-box method.  I&#39;ll fix that by reordering the definitions; meanwhile you can fix that by just eta-expanding your use of &quot;compose&quot;.<br>

</div><div class="gmail_extra"><br clear="all"><div>Carl Eastlund</div>
<br><br><div class="gmail_quote">On Fri, Aug 16, 2013 at 5:41 PM, Carl Eastlund <span dir="ltr">&lt;<a href="mailto:cce@ccs.neu.edu" target="_blank">cce@ccs.neu.edu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div dir="ltr">The method names are always going to be in the context of the generic interface name.  There&#39;s nowhere else they can come from.<span class="HOEnZb"><font color="#888888"><br></font></span></div><div class="gmail_extra">

<span class="HOEnZb"><font color="#888888"><br clear="all"><div>Carl Eastlund</div></font></span><div><div class="h5">
<br><br><div class="gmail_quote">On Fri, Aug 16, 2013 at 5:39 PM, J. Ian Johnson <span dir="ltr">&lt;<a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


WRT the struct abstraction, using syntax-local-introduce on #&#39;gen:binds-variables seemed to do the trick, oddly.<br>
<span><font color="#888888">-Ian<br>
</font></span><div>----- Original Message -----<br>
From: &quot;Carl Eastlund&quot; &lt;<a href="mailto:cce@ccs.neu.edu" target="_blank">cce@ccs.neu.edu</a>&gt;<br>
To: &quot;J. Ian Johnson&quot; &lt;<a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a>&gt;<br>
Cc: &quot;dev&quot; &lt;<a href="mailto:dev@racket-lang.org" target="_blank">dev@racket-lang.org</a>&gt;<br>
</div><div><div>Sent: Friday, August 16, 2013 5:23:33 PM GMT -05:00 US/Canada Eastern<br>
Subject: Re: [racket-dev] Generics scoping issues<br>
<br>
<br>
Okay, let me dig into this. The expansion of define/generic is an odd thing in the way it treats the method names; I&#39;m not at all sure I&#39;ve gotten it right, or that it&#39;s clear what &quot;right&quot; should even be. I&#39;ll get back to you shortly.<br>



<br>
<br>
<br>
Carl Eastlund<br>
<br>
<br>
On Fri, Aug 16, 2013 at 5:17 PM, J. Ian Johnson &lt; <a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a> &gt; wrote:<br>
<br>
<br>
Re: problem 1 - ah yes I see.<br>
Problem 2:<br>
In the body of def-free:<br>
<br>
generic-problems.rkt:16:26: define/generic: free is not a method of generic interfaces gen:binds-variables<br>
at: free<br>
in: (define/generic gfree free)<br>
<br>
This compiles if I additionally supply def-free with free, but it doesn&#39;t run:<br>
free-box: undefined;<br>
cannot reference an identifier before its definition<br>
in module: &quot;/home/ianj/projects/oaam/code/generic-problems.rkt&quot;<br>
context...:<br>
/home/ianj/projects/oaam/code/generic-problems.rkt: [running body]<br>
<br>
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&#39;t work anymore:<br>
<br>
(define-syntax-rule (astruct name (fields ...) (methods ...))<br>
(struct name exp (fields ...) #:transparent #:methods gen:binds-variables [methods ...]))<br>
<br>
(astruct avar (name)<br>
[(def-free e gfree free bound avar [(x) (if (x . ∈ . bound) ∅ (set x))])])<br>
<br>
generic-problems.rkt:31:27: define/generic: free is not a method of generic interfaces gen:binds-variables<br>
at: free<br>
in: (define/generic gfree free)<br>
<br>
<br>
<br>
<br>
----- Original Message -----<br>
From: &quot;Carl Eastlund&quot; &lt; <a href="mailto:cce@ccs.neu.edu" target="_blank">cce@ccs.neu.edu</a> &gt;<br>
To: &quot;J. Ian Johnson&quot; &lt; <a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a> &gt;<br>
Cc: &quot;dev&quot; &lt; <a href="mailto:dev@racket-lang.org" target="_blank">dev@racket-lang.org</a> &gt;<br>
Sent: Friday, August 16, 2013 4:50:53 PM GMT -05:00 US/Canada Eastern<br>
Subject: Re: [racket-dev] Generics scoping issues<br>
<br>
<br>
<br>
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&#39;s by design.<br>
<br>
Problem 2 -- what error message or unexpected behavior are you getting? That should work, it sounds like a bug in define/generic if it&#39;s not working.<br>
<br>
<br>
<br>
Carl Eastlund<br>
<br>
<br>
On Fri, Aug 16, 2013 at 4:36 PM, J. Ian Johnson &lt; <a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a> &gt; wrote:<br>
<br>
<br>
I&#39;m starting to use generics, and me being myself, I wrote some macros to make writing method definitions easier.<br>
But, I&#39;m seeing that #:methods seems to rebind method identifiers in a way that hygiene interferes with.<br>
<br>
I would expect to be allowed to do the following two things (problems annotated):<br>
<br>
(struct exp (label fvs-box)) ;; parent struct for all expressions<br>
(define-generics binds-variables<br>
[free-box binds-variables]<br>
[free binds-variables #:bound [bound]]<br>
#:fallbacks [(define (free e #:bound [bound ∅]) ∅)<br>
(define free-box exp-fvs-box)]<br>
#:fast-defaults ([(compose unbox free-box)<br>
(define (free e #:bound bound) (unbox (free-box e)))])) ;; problem 1: free-box not in scope<br>
<br>
(define-syntax-rule (def-free e gfree bound struct [(pats ...) rhss ...])<br>
(begin<br>
(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.<br>
(define (free e #:bound [bound ∅])<br>
(match e [(struct _ fvs-box pats ...)<br>
(set-box! fvs-box<br>
(let () rhss ...))]))))<br>
<br>
(struct var exp (name) #:transparent<br>
#:methods gen:binds-variables<br>
[(def-free e gfree bound var [(x) (if (x . ∈ . bound) ∅ (set x))])])<br>
<br>
I have workarounds thanks to stamourv, but they&#39;re unpleasant:<br>
Problem 1: define free in fast-defaults as an eta-expansion of a definition outside the define-generics form that does what you want.<br>
Problem 2: add free as a parameter to def-free, and pass free in at all uses of def-free.<br>
<br>
The first problem seems like more of a programming error than the use of the wrong tool.<br>
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.<br>
<br>
Are these expectations unreasonable/against the design decisions for generics?<br>
Thanks,<br>
-Ian<br>
<br>
_________________________<br>
Racket Developers list:<br>
<a href="http://lists.racket-lang.org/dev" target="_blank">http://lists.racket-lang.org/dev</a><br>
<br>
<br>
<br>
<br>
</div></div></blockquote></div><br></div></div></div>
</blockquote></div><br></div>