Subject: Re: Idiom to call function from string
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 10 Jul 2006 04:37:12 -0500
Newsgroups: comp.lang.lisp
Message-ID: <bu2dnVZQF-5Vgi_ZnZ2dnUVZ_oydnZ2d@speakeasy.net>
Pascal Bourguignon  <pjb@informatimago.com> wrote:
+---------------
| rpw3@rpw3.org (Rob Warnock) writes:
| > Now as far as *building* that hash table automagically, here's
| > a case where Common Lisp really shines!
| >     (defvar *foo-functions* (make-hash-table :test #'equal))
| >
| >     (defmacro def-foo-function (name &body body)
| >       `(progn (defun ,name () ,@body)
| > 	          (setf (gethash ,(string-downcase (symbol-name name))
| > 			         *foo-functions*)
| >                     #',name)))
| 
| If you want to COMPILE-FILE and still use it at run-time after
| a LOAD of the .fasl, it'll be a little more complicated...
+---------------

Hunh? I'm generally aware of those issues, but I thought I was
careful to make the macro expand into things that would build
the table at LOAD time, rather than at compile time. Did I miss
something obvious? It works in CMUCL, at least:

    > (compile-file "foo-hash")
    ; Python version 1.1, VM version Intel x86 on 10 JUL 06 02:15:58 am.
    ; Compiling: /u/rpw3/foo-hash.lisp 10 JUL 06 02:11:29 am
    ; Converted DEF-FOO-FUNCTION.
    ; Compiling DEFMACRO DEF-FOO-FUNCTION: 
    ; Converted FOO-DISPATCH.
    ; Compiling DEFUN FOO-DISPATCH: 
    ; Converted FOO-HELLO.
    ; Compiling DEF-FOO-FUNCTION HELLO: 
    ; Converted FOO-BYE.
    ; Compiling DEF-FOO-FUNCTION BYE: 
    ; Byte Compiling Top-Level Form: 
    ; Byte Compiling Top-Level Form: 
    ; foo-hash.x86f written.
    ; Compilation finished in 0:00:01.
    #P"/u/rpw3/foo-hash.x86f"
    NIL
    NIL
    > (load *)

    ; Loading #P"/u/rpw3/foo-hash.x86f".
    T
    > (foo-dispatch "hello")
    Hello, world!
    NIL
    > (foo-dispatch "bye")
    Goodbye, cruel world!
    NIL
    > (foo-dispatch "gorp")
    Unknown function: "gorp"
    usage: ...whatever...blah...blah...
    NIL
    > 

It also works fine if the LOAD of the FASL is in a fresh image.

Or are you talking about adding additional DEF-FOO-FUNCTIONs at
run-time? That seems to work, too:

    > (load "foo-hash")

    ; Loading #P"/u/rpw3/foo-hash.x86f".
    T
    > (foo-dispatch "gorp")
    Unknown function: "gorp"
    usage: ...whatever...blah...blah...
    NIL
    > (def-foo-function gorp ()
	(format t "What is \"gorp\"?~%"))
    > (foo-dispatch "gorp")
    What is "gorp"?
    NIL
    > 

Run-time redefinitions work, too:

    > (def-foo-function gorp ()
	(format t "What is \"gorp\"?~%"))
    > (foo-dispatch "gorp")
    What is "gorp"?
    NIL
    > (def-foo-function gorp ()
	(format t "Gorp is another name for trailmix.~%"))

    #<Interpreted Function FOO-GORP {48935511}>
    > (foo-dispatch "gorp")
    Gorp is another name for trailmix.
    NIL
    > 

I admit that you need a little more mechanism if you want run-time
DEF-FOO-FUNCTION redefinitions to get automatically compiled, but
I'll leave that as "an exercise for the reader"...  ;-}


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607