Suppose there are several functions (or macros):
func-aa-1-1
func-aa-2-1
func-bb-1-3
Is there a way to call these functions like this:
(call-function 'aa 1 1) => (func-aa-1-1)
(call-function 'bb 1 3) => (func-bb-1-3)
And, if the expected function doesn't exist, how to emit warning?
Thanks.
One solution that came to my mind is that save all available rules in
a file, like:
(AA 1 2 func-aa-1-1)
(AA 2 1 func-aa-2-1)
(BB 1 3 func-bb-1-3)
In "call-function", first read the file, then retrieve the function
name by searching. If no matching functions, report an error.
As the rules may change, I don't want these rules to be hard-coded in
the program.
My solution can meet my requirement, but is there a better solution?
normanj <·······@gmail.com> writes:
> One solution that came to my mind is that save all available rules in
> a file, like:
> (AA 1 2 func-aa-1-1)
> (AA 2 1 func-aa-2-1)
> (BB 1 3 func-bb-1-3)
>
> In "call-function", first read the file, then retrieve the function
> name by searching. If no matching functions, report an error.
>
> As the rules may change, I don't want these rules to be hard-coded in
> the program.
> My solution can meet my requirement, but is there a better solution?
Yes, this is what you should do.
The rules can be saved in the sources, there's not necessarily a need
for an external file.
Now, the presence of these digits is strange. Couldn't they be
parameters to the functions? Do you have a lot of them?
(defvar *name-to-function-map*
'((aa func-aa)
(bb func-bb)
(cc func-cc)))
(defun call-function (name arguments)
(let ((fun (cdr (assoc name *name-to-function-map*))))
(if fun
(apply fun arguments)
(error "No user function named ~S" name))))
(call-function 'aa 1 2)
(call-function (read) (read) (read))
--
__Pascal Bourguignon__
>
> Now, the presence of these digits is strange. Couldn't they be
> parameters to the functions? Do you have a lot of them?
>
Sorry, those digits should be replaced with normal strings.
All those parameters have nothing to do with the parameters
of functions/macros, they are only related with their names.
Yes, maybe hundreds.
>
> (defvar *name-to-function-map*
> '((aa func-aa)
> (bb func-bb)
> (cc func-cc)))
>
> (defun call-function (name arguments)
> (let ((fun (cdr (assoc name *name-to-function-map*))))
> (if fun
> (apply fun arguments)
> (error "No user function named ~S" name))))
>
> (call-function 'aa 1 2)
> (call-function (read) (read) (read))
>
This could be taken as a solution.
normanj <·······@gmail.com> writes:
>>
>> Now, the presence of these digits is strange. �Couldn't they be
>> parameters to the functions? �Do you have a lot of them?
>>
> Sorry, those digits should be replaced with normal strings.
> All those parameters have nothing to do with the parameters
> of functions/macros, they are only related with their names.
> Yes, maybe hundreds.
>
>
>>
>> (defvar *name-to-function-map*
>> � '((aa func-aa)
>> � � (bb func-bb)
>> � � (cc func-cc)))
>>
>> (defun call-function (name arguments)
>> � �(let ((fun �(cdr (assoc name *name-to-function-map*))))
>> � � � (if fun
>> � � � � (apply fun arguments)
>> � � � � (error "No user function named ~S" name))))
>>
>> (call-function 'aa 1 2)
>> (call-function (read) (read) (read))
>>
>
> This could be taken as a solution.
Given the number of functions, it might be worthwhile to use a
hash-table for the map.
(defvar *name-to-function-map*
(make-hash-table :test (function equal))) ; case sensitive strings, or else equalp
(dolist (pair '( (func-aa-1-2 . (aa one two)) ; which is the same to write (func-aa aa one two)
(func-bb-3-2 . (bb three two))
... ))
(setf (gethash (cdr pair) *name-to-function-map*) (car pair)))
and then use (gethash name *name-to-function-map*) instead of (cdr (assoc ...)),
with name bound to (aa one two), etc.
--
__Pascal Bourguignon__
>
> Now, the presence of these digits is strange. Couldn't they be
> parameters to the functions? Do you have a lot of them?
>
Sorry, those digits should be replaced with normal strings.
All those parameters have nothing to do with the parameters
of functions/macros, they are only related with their names.
Yes, maybe hundreds.
>
> (defvar *name-to-function-map*
> '((aa func-aa)
> (bb func-bb)
> (cc func-cc)))
>
> (defun call-function (name arguments)
> (let ((fun (cdr (assoc name *name-to-function-map*))))
> (if fun
> (apply fun arguments)
> (error "No user function named ~S" name))))
>
> (call-function 'aa 1 2)
> (call-function (read) (read) (read))
>
This could be taken as a solution.
On Apr 29, 11:09 am, normanj <·······@gmail.com> wrote:
> Suppose there are several functions (or macros):
> func-aa-1-1
> func-aa-2-1
> func-bb-1-3
> Is there a way to call these functions like this:
> (call-function 'aa 1 1) => (func-aa-1-1)
> (call-function 'bb 1 3) => (func-bb-1-3)
>
> And, if the expected function doesn't exist, how to emit warning?
>
> Thanks.
If you're only interested in functions, see the FIND-SYMBOL, SYMBOL-
FUNCTION and FUNCALL (or APPLY) functions.
Macros instead can't be "called"; they are expanded before code is run
(actually, before code is even compiled!) so if you want to be able to
do your transformation on macros too, CALL-FUNCTION must be a macro
itself, expanding to the proper call (the name would be a bit
misleading too). Note though that if CALL-FUNCTION was a macro, you'd
lose the ability to dynamically determining which function/macro to
invoke, i.e.
(let ((x 'aa))
(call-function x 1 2))
would expand to (x-1-2) and NOT (aa-1-2)!
Furthermore, using a macro would prevent you from detecting if you're
invoking a nonexistent function, unless you define the function before
the macro is run (and use FBOUNDP on the generated symbol to see if it
names a function): this means using EVAL-WHEN when defining the
function, and things grow a another little bit more complex :)
So, maybe you're trying to solve the wrong problem; what are you
exactly trying to achieve?
hth,
Alessio Stalla
On Apr 29, 4:09 am, normanj <·······@gmail.com> wrote:
> Suppose there are several functions (or macros):
> func-aa-1-1
> func-aa-2-1
> func-bb-1-3
I'm not entirely sure what you're trying to accomplish here, but where
are FUNC-AA-1-1, FUNC-AA-2-1, etc, coming from? If they already exist
for you, I have nothing. But if you're writing those yourself, too,
I'd
just use a generic function with a lot of EQL specifiers:
(defmethod call-function ((sym (eql 'aa)) (a1 (eql 1)) (a2 (eql 1)))
(frobnicate-wisely-on-aa-1-1))
Basically, just ask CLOS to handle the lookup table for you.
--
wm
In article
<····································@w8g2000prd.googlegroups.com>,
normanj <·······@gmail.com> wrote:
> Suppose there are several functions (or macros):
> func-aa-1-1
> func-aa-2-1
> func-bb-1-3
> Is there a way to call these functions like this:
> (call-function 'aa 1 1) => (func-aa-1-1)
> (call-function 'bb 1 3) => (func-bb-1-3)
>
> And, if the expected function doesn't exist, how to emit warning?
>
> Thanks.
1) create a string with the function name (upper case!)
2) create a symbol from the string (use INTERN)
3) check if the symbol names a function (use FBOUNDP)
4) use FUNCALL on the symbol to call that function
if you really have macros replace 4) with:
4) create a list with the name of the function/macro as an element
5) call EVAL with the list as an argument
--
http://lispm.dyndns.org/
> [snip]
>
> if you really have macros replace 4) with:
>
> 4) create a list with the name of the function/macro as an element
> 5) call EVAL with the list as an argument
>
Yeah, I hadn't thought about EVAL. So actually call-function can be a
function AND invoke macros. You could even use EVAL to build a lambda
calling your macro, as in (eval '(lambda () (my-macro-call))), and
then compile, cache or do whatewer you want with your lambda.
cheers
AS
>
> 1) create a string with the function name (upper case!)
> 2) create a symbol from the string (use INTERN)
> 3) check if the symbol names a function (use FBOUNDP)
> 4) use FUNCALL on the symbol to call that function
>
> if you really have macros replace 4) with:
>
> 4) create a list with the name of the function/macro as an element
> 5) call EVAL with the list as an argument
>
That is exactly what I want to achieve. Thanks.