[racket] Call by Name
Thanks to all for the workable solutions. I quickly implemented Ian's idea
and it is working for me... thanks again!
Here is a little background so you can better educate me:
As I've been learning Racket I've created a file called play.rkt that
contains useful code I've learned. Its primary purpose is to allow me to
quickly search for techniques and code that I vaguely remember. As I built
the file I created test functions alongside the code to make sure it is
working called test1 ... testn. I originally used test-engine to run these
tests. A nice feature of this setup was that I could use (test) to run all
the tests and (time (test)) to see how long they all took. When submodules
came out I switched to rackunit (module+ test ...) and could run all the
tests simply by hitting the "run" button in DrRacket. This worked fine but
I was just a little bothered that I could no longer see how long they all
take to run.
This morning I thought, "The test functions all look the same, there has to
be a way to call them all in a simple function that I can then run with
(time (call-fns))." Ian's code does this for me
without having to add a thousand extra lines to the existing file. Now I
hit "run" which checks that they are working, then type (time (call-fns))
if I want to see how long they take to run (without the return value
checking). This is workable for me. There are probably better ways and I
admit that this solution rested on a really bad naming convention
(test1...), but this is not production code, just a little something "on
the side" as it were.
Regards,
-Joe
On Tue, Nov 27, 2012 at 11:57 AM, Eli Barzilay <eli at barzilay.org> wrote:
> A few minutes ago, J. Ian Johnson wrote:
> > If you don't need to dispatch on name at runtime, you can write a
> > macro for this and use format-id to construct the identifier naming
> > the function. Otherwise you would need to use eval, which is highly
> > inadvisable.
>
> A few minutes ago, David Van Horn wrote:
> >
> > This is a slight variation on Ian's suggestion. It uses a macro
> > (id-in name n m) that constructs a list consisting of the elements
> > namen ... namem-1.
>
> These suggestions are not too useful, since they both basically
> provide an alternative syntax for something that is already in the
> code -- for example, the second one works only in cases like
> (id-in f 1 4) where you could just as well remove the space and use
> `f1'. (Realizing how they're not useful is probably a good exercise
> in "getting" macors, or maybe also getting the difference between
> macros and `eval' (and fexprs...).)
>
> In any case, here's another thing to consider, which is more likely to
> be a good solution when you run into such a problem: build a table
> that maps names to functions:
>
> (define function-names (make-hash))
> (define (call-by-name name . args)
> (apply (hash-ref function-names name) args))
>
> And when you define a function, add it to the table too:
>
> (define (test1) 'foo)
> (hash-set! function-names "test1" test1)
> (define (test2) 'bar)
> (hash-set! function-names "test2" test2)
> (call-by-name (format "test~a" (add1 (random 2))))
>
> This is looks verbose -- but that's fixable with a very simple macro:
>
> (define-syntax-rule (define/name (name . xs) body ...)
> (begin (define (name . xs) body ...)
> (hash-set! function-names (symbol->string 'name) name)))
> (define/name (test1) 'foo)
> (define/name (test2) 'bar)
> (call-by-name (format "test~a" (add1 (random 2))))
>
>
> --
> ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
> http://barzilay.org/ Maze is Life!
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20121127/f6fe7975/attachment-0001.html>