<br><br><div class="gmail_quote">On Wed, Sep 15, 2010 at 18:29, Robby Findler <span dir="ltr">&lt;<a href="mailto:robby@eecs.northwestern.edu">robby@eecs.northwestern.edu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

I must admit, what you&#39;ve done is quite the clever hack. You&#39;re<br>
loading the same file both at compile and and at runtime. At compile<br>
time you look at the exports using the (normally) runtime inspection<br>
facilities of the class system and use that to guide how compilation<br>
then happens of the module that interacts with the same file at<br>
runtime.<br></blockquote><div><br>This idea is in fact directly inspired by a runtime-path issue where Sam<br>told me to put some function definition in a separate module in import<br>it both with `require&#39; and `require (for-syntax ....)&#39;.<br>

(&quot;define-runtime-path-list and find-files&quot; thread, July 5th)<br>Reasoning by analogy, however shallow sometimes, can sometimes be <br>of great help ;)<br><br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">



This hack will have limitations, </blockquote><div><br>Do you have specific ones in mind?<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

but you could take this one step<br>
further by having the argument to your macro be an identifier and then<br>
taking the symbolic name of the identifier and passing that to<br>
dynamic-require (at compile time) to get the actual class you want.<br></blockquote><div><br>That is a nice idea, I&#39;ll try that.<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">


<br>
If you can change the file that defines a%, you can make it export a<br>
kind of &quot;table of contents&quot; and then iterate over that too.<br></blockquote><div><br>You mean over exported classes? <br><br><br><br>Btw, here is an improvement of the code:<br>Now only a single  call to define-class-&gt;singleton is sufficient, which makes<br>

things simpler.<br><br>#lang racket<br><br>(require (for-syntax racket/class))<br><br>;; Defines func as a sender of method to param-obj (parameter object).<br>;; Helper for define-class-&gt;singleton.<br>(define-syntax-rule (define-singleton-sender func param-obj method)<br>

  (begin ;(printf &quot;define-sender: ~s ~s ~s\n&quot; &#39;func &#39;obj &#39;meth)<br>         (define (func . args)<br>           (send/apply (param-obj) method args))))<br><br>#|<br>Defines a function for each public method of class%,<br>

called on the default object held by the current-obj-id parameter.<br><br>class%: a class, which must be available both at runtime (require) <br>  and at compile time (require for-syntax).<br>current-obj-id: an id that will be defined as a parameter <br>

  which initial value is current-obj-exp.<br><br>Remarks:<br>- class% must be available at runtime (for normal use) and at compile-time<br>(for inspection of the method names and definition of functions).<br>- The &quot;internal&quot; class-&gt;singleton macro is necessary so that it can be<br>

abstracted over class%, because it cannot be an argument to the call<br>to class-&gt;singleton.<br>(see &quot;Help: Passing a class to a macro and not an identifier&quot;, Sept. 15th.)<br>- Another tricky part is the #&#39;id for datum-&gt;syntax: it is not possible to<br>

directly use one of the parameter of the top macro instead because<br>they exist at compile time, so that would define the names for compile time.<br>But passing current-obj-id to class-&gt;singleton will define an id at runtime,<br>

and the function names are then defined in the right phase.<br>Maybe there is a better way to do that.<br>|#<br>(define-syntax-rule (define-class-&gt;singleton class% current-obj-id current-obj-exp)<br>  (begin<br>    (define-syntax (class-&gt;singleton stx)<br>

      (syntax-case stx ()<br>        [(_ id)<br>         (with-syntax ([(name (... ...))<br>                        ; #&#39;id: names are defined for runtime<br>                        (map (λ(n)(datum-&gt;syntax #&#39;id n)) <br>

                             (interface-&gt;method-names (class-&gt;interface class%)))])<br>           #&#39;(begin (define-singleton-sender name current-obj-id name)<br>                    (... ...)))]))<br>    (define current-obj-id (make-parameter current-obj-exp))<br>

    (class-&gt;singleton current-obj-id) ; pass a runtime identifier<br>    ))<br><br>    <br>    <br><br>#| Tests |#<br><br>#| file &quot;a.rkt&quot;:<br>#lang racket<br><br>(provide a% b%)<br><br>(define a%<br>  (class object% (super-new)<br>

    (init-field val)<br>    <br>    (define/public (get-the-val)<br>      val)<br>    ))<br><br>(define b%<br>  (class object% (super-new)<br>    (init-field valb)<br>    <br>    (define/public (get-the-valb)<br>      valb)<br>

    ))<br>|#<br><br>(require &quot;a.rkt&quot;<br>         (for-syntax &quot;a.rkt&quot;))<br><br>; Instantiate the macro for a% :<br>(define-class-&gt;singleton a% current-a (new a% [val 3]))<br><br><br>(get-the-val)<br>

<br>(parameterize ([current-a (new a% [val 5])])<br>  (get-the-val))<br><br>(get-the-val)<br><br>(define-class-&gt;singleton b% current-b (new b% [valb &quot;b&quot;]))<br>(get-the-valb)<br><br>;|#<br></div></div>