From: normanj
Subject: automatically call functions based on arguments
Date: 
Message-ID: <5a39817b-35cc-483c-878c-7e69891cba45@w8g2000prd.googlegroups.com>
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.

From: normanj
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <169cca3b-7ad3-47b9-8c24-df20015a7015@l25g2000prd.googlegroups.com>
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?
From: Pascal J. Bourguignon
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <7c63u04mnb.fsf@pbourguignon.anevia.com>
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__
From: normanj
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <89be7d36-1422-4473-8aa3-577be8d17666@v26g2000prm.googlegroups.com>
>
> 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.
From: Pascal J. Bourguignon
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <7cskx33jk4.fsf@pbourguignon.anevia.com>
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__
From: normanj
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <e382efa9-49a9-4e48-a418-9455d58117a2@w8g2000prd.googlegroups.com>
>
> 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.
From: Alessio Stalla
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <843739e6-4b7c-4985-8e84-acc526e09eda@27g2000hsf.googlegroups.com>
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
From: ········@gmail.com
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <3dd0aafd-ae4a-4b19-91b3-3411e975f1e6@34g2000hsh.googlegroups.com>
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
From: ········@gmail.com
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <623e0a57-e731-471e-a27b-88b24ea143d3@d1g2000hsg.googlegroups.com>
> just use a generic function with a lot of EQL specifiers:

Erm.  EQL specializers, not specifiers.

--
wm
From: Rainer Joswig
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <joswig-DB1D7E.11355429042008@news-europe.giganews.com>
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/
From: Alessio Stalla
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <8dcfa57a-cc67-4d64-9abc-5244c3dad737@m73g2000hsh.googlegroups.com>
> [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
From: normanj
Subject: Re: automatically call functions based on arguments
Date: 
Message-ID: <d4554e38-c7e1-4734-8243-ca8ca238de20@u36g2000prf.googlegroups.com>
>
> 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.