From: Jeff
Subject: Finding a function at runtime
Date: 
Message-ID: <cdr3ro$423@odah37.prod.google.com>
I'm trying to find an elegant way of finding a function at runtime
(using a string name). The closest methods I've found are COERCE or
EVAL. Example:

(defun find-function (string)
(let ((sym (find-symbol string)))
(when sym (coerce sym 'function))))

Using coerce works for some functions, but not all. For example, it
will work for "+", but not for "list". Very puzzling. My other method
(more hack-ish):

(defun find-function (string)
(with-input-from-string (stream (concatenate 'string "#'" string))
(eval (read stream))))

This one works just fine, but feels way to hack-ish. I would think
there is a nice function that does what I want (like FIND-SYMBOL), but
I can't seem to find it anywhere (google, HyperSpec, PG's books). Is
there one?

OTOH, perhaps if I describe my problem, there is an easier solution.
Imagine a text-based game (ie, "get key", "unlock door", "go north"). I
want to be able to parse the first word (ie "get") and return a
function I've already defined that will be called with the second
parsed symbol (ie "key"). If no function exists, then, of course, an
error is returned.

I could always just have a hash table of symbols and their equivelant
functions, but I was hoping there was something simpler. Thanks in
advance for any suggestions!

Jeff

From: Marco Baringer
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <m23c3iomw4.fsf@convey.it>
"Jeff" <···@insightbb.com> writes:

> I could always just have a hash table of symbols and their equivelant
> functions, but I was hoping there was something simpler. Thanks in
> advance for any suggestions!

it's as simple as:

(defcommand "unlock" (what)
  ...)

(defcommand "get" (what)
  ...)

and then:

(call-command command-name command-args)

here's some sample code to get you started:

(defparameter *command-table* (make-hash-table :test 'equal))

(defmacro defcommand (name command-args &body body)
  (assert (stringp name)
          (name)
          "NAME must be a string, not ~S." name)
  `(setf (gethash ,name *command-table*)
         (lambda ,command-args
           ,@body)))

(defun call-command (name args)
  (let ((command (gethash name *command-table*)))
    (if command
        (apply command args)
        (error "Unknown command: ~S." name))))

All in all I find this much simpler than the symbol munging stuff
you're using now.

-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen
From: Pascal Costanza
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <cdr4vd$14bo$1@f1node01.rhrz.uni-bonn.de>
Jeff wrote:

> I'm trying to find an elegant way of finding a function at runtime
> (using a string name).

Check out symbol-function and fdefinition. symbol-function finds a 
(global) function based on its name which must be a symbol. fdefinition 
does the same but also works when the name is a list consisting of 'setf 
and a name (which means that it names a setter function).

There is intentionally no way to find local functions at runtime in 
order to allow the compiler to perform certain optimizations.


Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Marco Antoniotti
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <%reMc.5$Vn5.4313@typhoon.nyu.edu>
Jeff wrote:
> I'm trying to find an elegant way of finding a function at runtime
> (using a string name).

(defun find-function (string-name &optional (package *package*))
    (multiple-value-bind (name status)
          (find-symbol string-name package)
      (when (and status (fboundp name))
        (symbol-function name))))


Cheers
--
Marco
From: Jeff
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <cohMc.152353$IQ4.20231@attbi_s02>
Marco Antoniotti wrote:

> (defun find-function (string-name &optional (package package))
> (multiple-value-bind (name status)
> (find-symbol string-name package)
> (when (and status (fboundp name))
> (symbol-function name))))

Thank you all for very informative and good replies.

Jeff
From: Pascal Bourguignon
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <87fz7i4swv.fsf@thalassa.informatimago.com>
"Jeff" <···@insightbb.com> writes:

> I'm trying to find an elegant way of finding a function at runtime
> (using a string name). The closest methods I've found are COERCE or
> EVAL. Example:
> 
> (defun find-function (string)
> (let ((sym (find-symbol string)))
> (when sym (coerce sym 'function))))
> 
> Using coerce works for some functions, but not all. For example, it
> will work for "+", but not for "list". Very puzzling. My other method
> (more hack-ish):

Unsurprizingly, since, unless you've declared one, there's no function
named "list" in *PACKAGE* (which usually imports COMMON-LISP).

CL-USER> (find-symbol "list")
NIL
NIL
CL-USER> (find-symbol "LIST")
LIST
:INHERITED

> [...]
> OTOH, perhaps if I describe my problem, there is an easier solution.
> Imagine a text-based game (ie, "get key", "unlock door", "go north"). I
> want to be able to parse the first word (ie "get") and return a
> function I've already defined that will be called with the second
> parsed symbol (ie "key"). If no function exists, then, of course, an
> error is returned.
>
> I could always just have a hash table of symbols and their equivelant
> functions, but I was hoping there was something simpler. Thanks in
> advance for any suggestions!

There is something simplier, but you still want to have a hash table
of valid commands for your game!  You can't allow the users to call
random functions in the lisp system, some are "dangerous".


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Alan Crowe
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <86wu0u8n7z.fsf@cawtech.freeserve.co.uk>
Pascal Bourguignon wrote:
> > I could always just have a hash table of symbols and their equivelant
> > functions, but I was hoping there was something simpler. Thanks in
> > advance for any suggestions!
>
> There is something simplier, but you still want to have a hash table
> of valid commands for your game!  You can't allow the users to call
> random functions in the lisp system, some are "dangerous".

There is something troubling me with all this talk of hash
tables. Looking up strings in a hash table to see which
symbol they refer to is READ's job. It uses fancy hash
tables, called packages, with added bells and whistles, but
the underlying technology is the same. So the code goes like
this

(defpackage "ADVENTURE"
  (:use "CL")
  (:shadow "GO" "GET")
  (:export "PLAY" "GET" "KEY" "LAMP" "SWORD"
	   "GO" "NORTH" "SOUTH" "EAST" "WEST"))

(in-package "ADVENTURE")

(defvar *sack* '()
  "List of items carried by player")

(defvar *north* 0)
(defvar *east* 0)

(defun get (object)
  (push object *sack*))

(defun go (direction)
  (case direction
	(north (incf *north*))
	(south (decf *north*))
	(east (incf *east*))
	(west (decf *east*))))

(defun play ()
  (loop
   (print "We await your command, oh great one: ")
   (let ((command (let ((*package* (find-package "INPUT")))
		    (read))))
     (handler-case
      ;; Read has turned the string into a symbol,
      ;; Now it is funcall's turn, to spot that it has
      ;; been passed a symbol and look up the corresponding
      ;; function in the global environment
      (funcall (car command)(cadr command))
      (undefined-function(condition)
	(format t "You cannot do ~S~%"
		(cell-error-name condition)))))
   (format t "You are ~A north ~A east, holding ~&~A~%"
	   *north* *east* *sack*)))

(defpackage "INPUT"
  (:use "ADVENTURE")
  (:export get key lamp sword
	   go north south east west))

and the first few turns of the game go like this

* (load "interactive-input")

; Loading #p"/home/alan/Learning/lisp/packages/interactive-input.lisp".
T
* (in-package "ADVENTURE")

#<The ADVENTURE package, 6/13 internal, 10/21 external>
* (play)

"We await your command, oh great one: " (go north)
You are 1 north 0 east, holding 
NIL

"We await your command, oh great one: " (get key)
You are 1 north 0 east, holding 
(KEY)

"We await your command, oh great one: " (format disk)
You cannot do INPUT::FORMAT
You are 1 north 0 east, holding 
(KEY)

"We await your command, oh great one: " 

Notice that there is no entry for CL:FORMAT in the hash
table underneath the "INPUT" package, so typing in 
(format disk) could not access the CL command. 

In the footnote on page 548 of Common Lisp the Language 2
Steele encourages users 

   ... to turn off most macro characters, turn others into
   single-character object macros, and then use READ purely
   as a lexical analyzer on top of which to build a parser.

Alan Crowe
Edinburgh
Scotland
From: Kalle Olavi Niemitalo
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <87iscefiko.fsf@Astalo.kon.iki.fi>
Alan Crowe <····@cawtech.freeserve.co.uk> writes:

> Notice that there is no entry for CL:FORMAT in the hash
> table underneath the "INPUT" package, so typing in 
> (format disk) could not access the CL command. 

Well, cl:format also needs at least two arguments, and your
adventurous REPL will only provide one.  However, try these:

(cl:eval (cl:format cl:t "oops!~%"))
#.(cl:progn (cl:format cl:t "oops!~%") '(go home))

> In the footnote on page 548 of Common Lisp the Language 2
> Steele encourages users 
>
>    ... to turn off most macro characters, turn others into
>    single-character object macros, and then use READ purely
>    as a lexical analyzer on top of which to build a parser.

The colon is normally a constituent character.  To prevent using
it to select packages, you could indeed define it as a macro
character.

Even if you redefine "#." or all of "#", I think it would still
be prudent to bind *READ-EVAL* to NIL, in case the implementation
provides another syntax for this feature.
From: Christopher C. Stacy
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <uy8lajbbc.fsf@news.dtpq.com>
>>>>> On Sat, 24 Jul 2004 01:46:15 +0300, Kalle Olavi Niemitalo ("Kalle") writes:

 Kalle> Alan Crowe <····@cawtech.freeserve.co.uk> writes:
 >> Notice that there is no entry for CL:FORMAT in the hash
 >> table underneath the "INPUT" package, so typing in 
 >> (format disk) could not access the CL command. 

 Kalle> Well, cl:format also needs at least two arguments, and your
 Kalle> adventurous REPL will only provide one.  However, try these:

 Kalle> (cl:eval (cl:format cl:t "oops!~%"))
 Kalle> #.(cl:progn (cl:format cl:t "oops!~%") '(go home))

 >> In the footnote on page 548 of Common Lisp the Language 2
 >> Steele encourages users 
 >> 
 >> ... to turn off most macro characters, turn others into
 >> single-character object macros, and then use READ purely
 >> as a lexical analyzer on top of which to build a parser.

 Kalle> The colon is normally a constituent character.  To prevent using
 Kalle> it to select packages, you could indeed define it as a macro
 Kalle> character.

 Kalle> Even if you redefine "#." or all of "#", I think it would still
 Kalle> be prudent to bind *READ-EVAL* to NIL, in case the implementation
 Kalle> provides another syntax for this feature.

It might be more fun to forget to bind it.
From: Christopher C. Stacy
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <uu0vyj84b.fsf@news.dtpq.com>
A few random comments for you to think about in 
your Adventure program adventures.

Early in the history of Lisp, back when it didn't have strings, 
it was typical to implement user commands and communication using
symbols and just calling READ to get them.  A little later, people
wrote fancier parsers that gave a nicer visual interaction, and
only used symbols for the underlying (abstracted) concepts.
Going so far as having the user enter Lisp expressions like (GET BIRD) 
is quaint, but isn't how any "real" Lisp program would be written.

Being only 16 lines long, it's easy to understand what's going on 
in PLAY.  But the way your program is currently implementing things,
you're not making any functional abstractions.

You have wired in the idea that user actions are functions, and that
user mistakes are built-in Lisp conditions.  That would be sort of
like writing assembler code where you test, say, the sign bit in a
word to see if an error has occurred.  It would be nicer to test a 
bit that was symbolically defined, using a name like USER-VERB-ERROR.
Of course, a larger issue is whether or not Lisp conditions are the
appropriate mechanism to indicate and deal with  a user error.
How do you want to organize the handling of user "errors"?
Where do they occur?

Your program is  going to be hard to maintain, because you have
decided that user verb problems are the same thing as undefined
function errors.  What if there is an undefined function bug in
some verb subroutine that the user successfully calls?

Now, you're already not calling EVAL, having explicated the FUNCALL.
But the user is still really is typing in a Lisp expression.
Your PLAY is just a glorified READ-EVAL-PRINT loop.
The next step might be to abstract the user input so that he's
not typing a SEXPR that you'll just pick apart and hand to FUNCALL.
As long as you're picking the input apart, why not accept a more
natural looking command (such as "pick up the big red pirate's knife").
This would still turn into some kind a function-call, eventually.
The command "pick up" might resolve into the GET function.  
But when you look up the verb "pick up" you'll know if it has an
associated function.  If there is none, then you print some kind 
of "I don't understand" message, rather than trying to FUNCALL anything.  
The arguments to the verb functions might still be symbols: perhaps
the "big red pirate's knife" maps to PIRATES-KNIFE.

What happens when the user does (GET INKJET-PRINTER) which is not one
of the objects you had preconceived?  How about (GET INKJET PRINTER)?

Whether you would use hash table or some other data structure to
perform the mapping of strings into object (ahem) objects (eg. symbols)
would be a basic programming decision.

You'll probably have locations, too.  These might be represented in
your program as symbols like TRYING-TO-GET-INTO-CAVE, AT-WITTS-END,
and NE-SIDE-OF-CHASM.  They might be referenced in some kind of map
data structure.  Those locations might have properties associated with
them (through property lists, or as part of some other data structure).
One such property might be the location's name (more suitable for
printing than the symbol name) and the scenery description.
Presumably locations will have contents?  I see no contents here.

A few style comments on your code:

1. Put spaces between function arguments, rather than just using
   parenthesis as the seperators.    (FOO (BAR) (BAZ))
   rather than                       (FOO(BAR)(BAZ)).
   Same thing for the argument (CONDITION) in your handler clause.

2. The indentation of your HANDLER-CASE is difficult to read.
   (Use the automatic smart Lisp-indenting feature in your editor.)
   indenting is critical when trying to understand your code. 
   Lots of beginners make mistakes that seem very mysterious to them,
   but which are totally obvious when the code has been indented properly.

3. In your loop you repeatedly bind *PACKAGE* near the READ.
   Is there any reason why you don't want it bound all the time?
   Alternatively, that (LET...(READ...)) is nicely isolated there in a
   way that you could easily snip it out into a seperate subroutine function.
   I'd seperate out the (more elaborate) user input routine from the main loop.

Have fun!
BE SURE TO SAVE YOUR CORE-IMAGE...
From: Alan Crowe
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <861xj1zmf4.fsf@cawtech.freeserve.co.uk>
Christopher C. Stacy wrote:
> A few random comments for you to think about in your
> Adventure program adventures.
 
Whoops, it looks like I cut too much context and didn't
choose which post to reply to with sufficient care.

It is the original poster "Jeff" <···@insightbb.com>
who is heading off on the adventure. He wrote

> OTOH, perhaps if I describe my problem, there is an easier
> solution.  Imagine a text-based game (ie, "get key",
> "unlock door", "go north"). I want to be able to parse the
> first word (ie "get") and return a function I've already
> defined that will be called with the second parsed symbol
> (ie "key"). If no function exists, then, of course, an
> error is returned.
>
> I could always just have a hash table of symbols and their
> equivelant functions, but I was hoping there was something
> simpler. Thanks in advance for any suggestions!

I've been learning the package system, so I wanted to share
my understanding that there are hash tables lurking
underneath packages.

Since I'm not very experienced with CL, I often go to the
trouble of trying out my suggestions before posting them on
c.l.l. Hence the code. My suggestions might not be good
ones, but they do actually work, and writing actual code is
chipping away at my lack of experience.

Christopher C. Stacy wrote:
> 3. In your loop you repeatedly bind *PACKAGE* near the READ.
>    Is there any reason why you don't want it bound all the time?

I bind *PACKAGE* near READ to make it easy for Jeff to see
what is going on.

Christopher C. Stacy wrote:
> Early in the history of Lisp, back when it didn't have
> strings, it was typical to implement user commands and
> communication using symbols and just calling READ to get
> them.  A little later, people wrote fancier parsers that
> gave a nicer visual interaction, and only used symbols for
> the underlying (abstracted) concepts.  Going so far as
> having the user enter Lisp expressions like (GET BIRD) is
> quaint, but isn't how any "real" Lisp program would be
> written.

Leaving READ behind, I still see the package system
providing an attractive dollop of functionallity. For
example one might later add flying to the game. Some
commands would work on the ground, while others would work
in the air. The simplest approach is two tables of valid
commands, one for each mode. That doesn't scale well to more
modes.

The usual idea is to partition the commands into sets and
put together a mode by listing the several sets of commands
that it permits. If one starts with hash tables one ends up
adding some kind of inheritance/union mechanism. But
packages provide that already. For example, with a file
defining the sets of symbols:

(defpackage "MASTER-COMMAND-LIST"
  (:use)
  (:nicknames "CMD")
  (:export "UP" "DOWN" "LEFT" "RIGHT" "GET"))

(in-package "CMD")
(cl:import 'cl:defpackage)

;;; Partion commands into three sets
;;; basic, walk-extra, fly-extra

(defpackage "BASIC"
  (:use "CMD")
  (:export left right))

(defpackage "WALK-EXTRA"
  (:use "CMD")
  (:export get))

(defpackage "FLY-EXTRA"
  (:use "CMD")
  (:export up down))

;;; assemble modes from components

(defpackage "WALK-MODE"
  (:use "BASIC" "WALK-EXTRA"))

(defpackage "FLY-MODE"
  (:use "BASIC" "FLY-EXTRA"))

we can use find-symbol

(find-symbol "GET" (find-package "FLY-MODE")) => NIL, NIL

(find-symbol "GET" (find-package "WALK-MODE")) 
=> MASTER-COMMAND-LIST:GET, :INHERITED

(find-symbol "UP" (find-package "FLY-MODE"))
=> MASTER-COMMAND-LIST:UP, :INHERITED

What do you think of using the package system like this? Use
or abuse?

Alan Crowe
Edinburgh
Scotland
From: Rainer Joswig
Subject: Re: Finding a function at runtime
Date: 
Message-ID: <joswig-29A5EC.20201423072004@news-50.dca.giganews.com>
In article <··········@odah37.prod.google.com>,
 "Jeff" <···@insightbb.com> wrote:

> I'm trying to find an elegant way of finding a function at runtime
> (using a string name). The closest methods I've found are COERCE or
> EVAL. Example:
> 
> (defun find-function (string)
> (let ((sym (find-symbol string)))
> (when sym (coerce sym 'function))))
> 
> Using coerce works for some functions, but not all. For example, it
> will work for "+", but not for "list". Very puzzling. My other method
> (more hack-ish):
> 
> (defun find-function (string)
> (with-input-from-string (stream (concatenate 'string "#'" string))
> (eval (read stream))))
> 
> This one works just fine, but feels way to hack-ish. I would think
> there is a nice function that does what I want (like FIND-SYMBOL), but
> I can't seem to find it anywhere (google, HyperSpec, PG's books). Is
> there one?
> 
> OTOH, perhaps if I describe my problem, there is an easier solution.
> Imagine a text-based game (ie, "get key", "unlock door", "go north"). I
> want to be able to parse the first word (ie "get") and return a
> function I've already defined that will be called with the second
> parsed symbol (ie "key"). If no function exists, then, of course, an
> error is returned.

See for example CLIM commands and command tables.

http://www.lispworks.com/reference/lw43/CLIM/html/climguide-190.htm#pgfId-407790

Note that there is a 'free' version of CLIM under development:
McCLIM. See here for more infos: http://mcclim.cliki.net/index

> 
> I could always just have a hash table of symbols and their equivelant
> functions, but I was hoping there was something simpler. Thanks in
> advance for any suggestions!
> 
> Jeff