(defvar *fun-table*
'(("+" . #'+)
("-" . #'-)
("*" . #'*)
("/" . #'/)))
(defun operate (op n1 n2)
(funcall (cdr (assoc op *fun-table* :test #'string=)) n1 n2))
When I try to call the function operate in the format as follows:
(operate "+" 1 2)
It failed. The error message is: *** - FUNCALL: (#'+) is not a
function name; try using a symbol instead.
Who can help me? I want to map a string to a function. So I can call
the corresponding function by giving the string.
On Oct 11, 8:46 pm, Andy <·······@gmail.com> wrote:
> (defvar *fun-table*
> '(("+" . #'+)
> ("-" . #'-)
> ("*" . #'*)
> ("/" . #'/)))
>
> (defun operate (op n1 n2)
> (funcall (cdr (assoc op *fun-table* :test #'string=)) n1 n2))
>
> When I try to call the function operate in the format as follows:
> (operate "+" 1 2)
> It failed. The error message is: *** - FUNCALL: (#'+) is not a
> function name; try using a symbol instead.
>
> Who can help me? I want to map a string to a function. So I can call
> the corresponding function by giving the string.
First you need to remember that #'+ is shorthand for (function +), so
*fun-table* is basically:
'(("+" . (function +))
("-" . (function -))
...)
Thank you very much. I have solved this problem.
On Oct 12, 10:13 am, Brian <··············@gmail.com> wrote:
> On Oct 11, 8:46 pm, Andy <·······@gmail.com> wrote:
>
> > (defvar *fun-table*
> > '(("+" . #'+)
> > ("-" . #'-)
> > ("*" . #'*)
> > ("/" . #'/)))
>
> > (defun operate (op n1 n2)
> > (funcall (cdr (assoc op *fun-table* :test #'string=)) n1 n2))
>
> > When I try to call the function operate in the format as follows:
> > (operate "+" 1 2)
> > It failed. The error message is: *** - FUNCALL: (#'+) is not a
> > function name; try using a symbol instead.
>
> > Who can help me? I want to map a string to a function. So I can call
> > the corresponding function by giving the string.
>
> First you need to remember that #'+ is shorthand for (function +), so
> *fun-table* is basically:
> '(("+" . (function +))
> ("-" . (function -))
> ...)
On Oct 11, 8:46 pm, Andy <·······@gmail.com> wrote:
> (defvar *fun-table*
> '(("+" . #'+)
> ("-" . #'-)
> ("*" . #'*)
> ("/" . #'/)))
>
> (defun operate (op n1 n2)
> (funcall (cdr (assoc op *fun-table* :test #'string=)) n1 n2))
>
> When I try to call the function operate in the format as follows:
> (operate "+" 1 2)
> It failed. The error message is: *** - FUNCALL: (#'+) is not a
> function name; try using a symbol instead.
>
> Who can help me? I want to map a string to a function. So I can call
> the corresponding function by giving the string.
E:\>irb --prompt xmp
def operate( op, n1, n2 )
n1.send( op, n2 )
end
==>nil
operate( "*", 7, 8 )
==>56
On Sun, 12 Oct 2008 15:17:20 +0200, André Thieme wrote:
> William James schrieb:
>
>> E:\>irb --prompt xmp
>> def operate( op, n1, n2 )
>> n1.send( op, n2 )
>> end
>> ==>nil
>> operate( "*", 7, 8 )
>> ==>56
>
> In Lisp it is 10% shorter:
> (defun operate (op n1 n2)
> (funcall op n1 n2))
>
> 9 code elements (Lisp) vs 10 code elements (Ruby).
So what? Who cares? Since when has counting code elements in toy
examples (and brain-dead ones at that) has become a basis for comparison
of languages?
Tamas
Rainer Joswig schrieb:
> In article <············@registered.motzarella.org>,
> André Thieme <······························@justmail.de> wrote:
>
>> William James schrieb:
>>
>>> E:\>irb --prompt xmp
>>> def operate( op, n1, n2 )
>>> n1.send( op, n2 )
>>> end
>>> ==>nil
>>> operate( "*", 7, 8 )
>>> ==>56
>> In Lisp it is 10% shorter:
>> (defun operate (op n1 n2)
>> (funcall op n1 n2))
>>
>> 9 code elements (Lisp) vs 10 code elements (Ruby).
>
> with the slight problem that FUNCALL does not work on strings...
Yes Rainer, you are right.
But anyway, it doesn’t matter, because this example illustrates
once again, as in *all* of Williamns examples, that one can do the
exactly equivalent solution in Lisp. He never showed how Ruby can
help with something by expressing the algorithm in an easier way.
He comes closest by using functions (like transpose for matrixes)
which are not available in standard lisp, but which come with Ruby.
This however does not impress anyone. Most likely there are several
functions defined in Lisp which are not present in Ruby.
But this is not the reason why Lisp is more powerful than Ruby in
most cases when non-scripting tasks but complex ones are to be solved.
Lisp allows us to reduce the complexity of allgorithms by offering ways
to express other kinds of abstractions in code.
So, let’s load our scripting lib in Lisp and say then
(defun operate (op n1 n2)
(send op n1 n2))
André
--
André Thieme <······························@justmail.de> writes:
> But anyway, it doesn’t matter, because this example illustrates
> once again, as in *all* of Williamns examples, that one can do the
> exactly equivalent solution in Lisp. He never showed how Ruby can
> help with something by expressing the algorithm in an easier way.
This is not surprising, when you know what Ruby is:
http://web.archive.org/web/20060522191515/http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/179642
| Ruby is a language designed in the following steps:
|
| * take a simple lisp language (like one prior to CL).
| * remove macros, s-expression.
| * add simple object system (much simpler than CLOS).
| * add blocks, inspired by higher order functions.
| * add methods found in Smalltalk.
| * add functionality found in Perl (in OO way).
Therefore Ruby is strictly less powerful than Common Lisp, by construction.
--
__Pascal Bourguignon__
From: Robert Maas, http://tinyurl.com/uh3t
Subject: Re: functions in a list
Date:
Message-ID: <rem-2008oct12-001@yahoo.com>
> From: Andy <·······@gmail.com>
> (defvar *fun-table*
> '(("+" . #'+)
> ("-" . #'-)
> ("*" . #'*)
> ("/" . #'/)))
==> *fun-table*
You're doing too much all at once there. You need to do just *one*
thing at a time and get that correct before doing the next thing,
and get *all* the various things correct before trying to combine
them. Pascal gave the most appropriate answer, telling what was
wrong with your attempt to set up your own set of mappings from
strings to functions independent of any package of symbols, while
others gave inappropriate answers, simply telling you to use
symbols instead of strings. For some applications using strings is
perfectly appropriate. The problem with Pascal's appropriate answer
is that it was somewhat cryptic. I'll try to give a less cryptic
answer, per my advice of doing just one thing at a time.
First I'll do the *obvious* thing you should have done next after
that defvar, namely evaluate *fun-table* to see what its value is
after you did the defvar, to see whether you assigned it the value
you expected. You can do that by using * whose value is
*fun-table*, or by using *fun-table* literally. Any of the
following, as the very next step in the REPL, will tell you the
value of *fun-table*.
(eval *)
(eval '*fun-table*)
(symbol-value *)
(symbol-value '*fun-table*)
*fun-table*
I personally prefer the first above because it's the least typing,
but if you mistakely do something else first, that will no longer
work because * will be moved to ** and there'll be a new * value.
But in any case, if you do *any* of those ways of learning the
value you assigend to *fun-table*, you will get this result:
(("+" FUNCTION +)
("-" FUNCTION -)
("*" FUNCTION *)
("/" FUNCTION /))
Oops, that's not at all what you expected. The CDR of each element
in the toplevel list is a list of two elements, the symbol FUNCTION
and one of the symbols denoting an arithmetic function. What you
probably expected was to have the CDR of each element be an actual
function object, like this:
(("+" . #<Function + {1297819}>)
("-" . #<Function - {1390DB9}>)
("*" . #<Function * {1084019}>)
("/" . #<Function / {1257279}>))
So already at that point you would (should) have seen you didn't
have the correct association list mapping strings to functions, so
you wouldn't have tried what you tried next, right?
So how do you get the global value you wanted in the first place?
(I'm not going to do your homework for you, but I'll coach you
toward getting the answer yourself by correct sequence of thoughts.)
OK, let's do just one thing at a time. See if you can find a way to
construct just the first element of that desired list, i.e. can you
construct just the single element:
("+" . #<Function + {1297819}>)
You want to construct a CONS cell whose CAR is that string but
whose CDR is that function object. Can you write one line of code
that will do that in the most simple manner?
> (defun operate (op n1 n2)
> (funcall (cdr (assoc op *fun-table* :test #'string=)) n1 n2))
This is correct, but *only* if you set up the correct value of
*fun-table* as I showed above. Let's postpone trying this until you
get that global value set up corectly, OK?
> Who can help me? I want to map a string to a function. So I can call
> the corresponding function by giving the string.
That's perfectly reasonable to want to do in some situations, you
just need to figure out how to set up that association list
correctly. But first figure out how to set up just one element of
that list, OK? One step at a time. Don't try to do several things
all at once when you don't yet know quite what you are doing. But
if you *insist* in trying a whole mess at one time, at least check
if you did it correctly, by (eval *) or somesuch after the (defvar ...)
before moving on to the next step, OK?
By the way, IMO that should have been defparameter instead of
defvar, because this is a *constant* that you are setting up for
your program to use, not something that your program will be
changing lots of times, but *you* may wish to change it from time
to time so you can't use defconstant. But that's a subtle issue you
can learn about later. If you really do want to learn that now:
DEFCONSTANT - for values that will never ever change
DEFPARAMETER - for configuration values you will set up manually
and perhaps change from run to run but your program won't be
changing
DEFVAR - for true variables that your *program* will be changing
Now I see that you thanked Pascal and said you have the problem
solved, but you didn't say what solution you found, so I don't know
whether you really solved your problem or evaded it by coding
things in a totally different way. I'm curious which is the case.
Please either answer my one-thing-at-a-time question above, or show
the complete solution you got from Pascal's help including printing
out the value of *fun-table* that you constructed. (It'll probably
be slightly different from what I got using CMU Common Lisp 18b,
because you're probably not using the same version of CMUCL as I
am, so I can tell whether you really got it right or just tried to
copy back my answer without actually getting the correct answer
yourself. See, the printout for a function object exposes some of
the internals of the implementation, namely the machine address
where the functions have been loaded, so you *can't* cheat by
copying somebody else's work without me noticing.)
If you cooperate with me, allowing me to tutor you in a proper
manner, one step at a time, I'll guide you through figuring out by
yourself how to:
- Build just one element of that association list (the task I
assigned you above).
- How to use copy&paste of that same syntax to build the whole
association list by simply repeating the same code for each of the
pairs in the association list.
- How to use the backquote macro to greatly reduce the amount of
syntax you would need to include in your source file to do
exactly the same thing by exactly the same method.
- How to write a MACRO to define a DSL (domain-specific language)
whereby you don't need the backquote macro, but instead can use
that ultra-compact notation you started with and automatically
convert it to what you need for this application.
(defmacro make-function-table (&body form) ...)
(defparameter *fun-table*
(make-function-table ("+" +) ("-" -) ("*" *) ("/" /)))
Note in your case you're using exactly the same string as the print
name of the corresponding function, but I assume you want a more
general mechanism, for example you can do this instead for fun:
(defparameter *weird-fun-table*
(make-function-table ("p" +) ("m" -) ("t" *) ("d" /)))
so then you can for example have ("p" 3 5) funny-evaluate to 8.
- How to write a recursive version of operate, which takes a
complete form as one parameter instead of operator and operands
separately, so that you can for example have ("p" 2 ("t" 7 5))
funny-evaluate to 37.
Andy <·······@gmail.com> writes:
> (defvar *fun-table*
> '(("+" . #'+)
> ("-" . #'-)
> ("*" . #'*)
> ("/" . #'/)))
>
> (defun operate (op n1 n2)
> (funcall (cdr (assoc op *fun-table* :test #'string=)) n1 n2))
>
> When I try to call the function operate in the format as follows:
> (operate "+" 1 2)
> It failed. The error message is: *** - FUNCALL: (#'+) is not a
> function name; try using a symbol instead.
>
> Who can help me?
Your brains.
> I want to map a string to a function.
Then why did you map strings to lists?
> So I can call
> the corresponding function by giving the string.
You shouldn't use unconspicious reader macros.
Just use normal s-exps.
Instead of writing 'x, write (quote x)
Instead of writing #'x, write (function x)
things should become clear then.
--
__Pascal Bourguignon__ http://www.informatimago.com/
ATTENTION: Despite any other listing of product contents found
herein, the consumer is advised that, in actuality, this product
consists of 99.9999999999% empty space.
In article
<····································@k36g2000pri.googlegroups.com>,
Andy <·······@gmail.com> wrote:
> (defvar *fun-table*
> '(("+" . #'+)
> ("-" . #'-)
> ("*" . #'*)
> ("/" . #'/)))
>
> (defun operate (op n1 n2)
> (funcall (cdr (assoc op *fun-table* :test #'string=)) n1 n2))
>
> When I try to call the function operate in the format as follows:
> (operate "+" 1 2)
> It failed. The error message is: *** - FUNCALL: (#'+) is not a
> function name; try using a symbol instead.
>
> Who can help me? I want to map a string to a function. So I can call
> the corresponding function by giving the string.
Interned symbols are usually used for this.
Symbols have a name and you can lookup an interned symbol from
a string. 'Interned' means that the symbol is registered
in some data structures - packages.
FIND-SYMBOL takes a string and optionally a package - the package
defaults to the current package, the value of *package*.
In the examples I just use the default package.
CL-USER 37 > (find-symbol "+")
+
:INHERITED
CL-USER 38 > (funcall (find-symbol "+") 3 4)
7
and:
CL-USER 39 > (funcall (find-symbol "SIN") 1.4)
0.98544974
CL-USER 40 > (defun operate (op1 n1 n2) (funcall (find-symbol op1) n1 n2))
OPERATE
CL-USER 41 > (operate "+" 3 4)
7
If you want to maintain your own mappings of strings to
functions you can use data structures like
* assoc lists
* hash-tables
* packages
The assoc list is simply something like:
(("+" . +) ("foo" . my-foo))
Note that the assoc list maps to symbols. You can also
map directly to function objects:
(list (cons "+" (function +))
(cons "sin" #'SIN))
See:
CL-USER 47 > (list (cons "+" (function +))
(cons "sin" #'SIN))
(("+" . #<Function + 20B0AC82>) ("sin" . #<Function SIN 205455E2>))
CL-USER 48 > (assoc "+" * :test #'string=)
("+" . #<Function + 20B0AC82>)
Hash tables and packages are left as an exercise. ;-)
--
http://lispm.dyndns.org/