Common Lisp: passing a function to a function and applying it 
Author Message
 Common Lisp: passing a function to a function and applying it

Hello,

Here is a simple function definition:

(defun plus-one (x) (+ x 1))
(plus-one 1) -> 2

Here is a function definition that makes use of another function:

(defun plus-two (x) (plus-one (plus-one x)))
(plus-two 2) -> 4

Now I would like to be able to write a function which can take arbitrary
functions in the parameter list and apply them to elements in the function
body. For this purpose I tried to write the conceptually simple function
apply-fun which would take a function f and a variable x to produce the
result of applying f to x. Unfortunately something went wrong:

(defun apply-fun (f x) (f x))
(apply-fun plus-two 4) -> *** - EVAL: variable PLUS-TWO has no value
                       -> Error: The variable PLUS-TWO is unbound.
                       -> Fast links are on: do (si::use-fast-links nil)
                       -> for debugging
                       -> Error signalled by EVAL.
                       -> Broken at APPLY-FUN.  Type :H for Help.

I also tried the following, but I got the same error.

(defun apply-fun (f x) (apply f (cons x NIL)))

Is there a way I can tell lisp that f is a function and not a variable?

Once I get this to work I should be able to write more complicated functions
which take functions in the parameter list. Any ideas of what might have
gone wrong in the definition of apply-fun ?

Thanks,

Neil



Fri, 02 Apr 2004 07:18:20 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

> (defun plus-one (x) (+ x 1))
> (defun plus-two (x) (plus-one (plus-one x)))
> (defun apply-fun (f x) (f x))
> (defun apply-funct (f x) (apply f (cons x NIL)))

Just to be a little bit clearer I was only asking for an explanation

(apply-funct 'plus-two 2)

works but the similar looking function application

(apply-fun 'plus-two 2)

does not work, resulting in the message:
*** - EVAL: the function F is undefined

Do I really have to use apply here or is there another way
so that I don't have to cons x into NIL?

Thanks,

Neil



Fri, 02 Apr 2004 07:33:08 GMT  
 Common Lisp: passing a function to a function and applying it
Common Lisp has two namespaces: The "regular" one, and one for
functions (and other operators). The first position in a list form
(meaning a list to be evaluated, like "(plus-one 3)") automatically
uses the operator namespace, whereas the other positions uses the
regular namespace.

Quote:

> Do I really have to use apply here or is there another way so that I
> don't have to cons x into NIL?

Your problem is that you have a function located in the regular
namespace, and you want to call it. The function FUNCALL exists for
this purpose. It accepts a function name (or an actual function
object), looks it up in the operator namespace, and applies it to the
rest of the arguments passed to it. (funcall 'plus-one 3) => 4.

--
Frode Vatvedt Fjeld



Fri, 02 Apr 2004 08:25:20 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

> Common Lisp has two namespaces: The "regular" one, and one for
> functions (and other operators). The first position in a list form
> (meaning a list to be evaluated, like "(plus-one 3)") automatically
> uses the operator namespace, whereas the other positions uses the
> regular namespace.

> Your problem is that you have a function located in the regular
> namespace, and you want to call it. The function FUNCALL exists for
> this purpose. It accepts a function name (or an actual function
> object), looks it up in the operator namespace, and applies it to the
> rest of the arguments passed to it. (funcall 'plus-one 3) => 4.

I guess funcall is similar to apply except it does not require the
arguments to be contained in a list. Correct?

Thank you for introducing me to the funcall lisp operator: it seems
to do exactly what I was looking for except that just like with apply
the GCL implementation does not seem to work with lambda functions,
unlike the clisp implementation:

CLISP> (funcall (lambda (x) (+ x 1)) 1)
-> 2

(hurray!)

GCL> (funcall (lambda (x) (+ x 1)) 1)
-> Error: The function LAMBDA is undefined.
Fast links are on: do (si::use-fast-links nil) for debugging
Error signalled by EVAL.
Broken at FUNCALL.  Type :H for Help.

(boooo!)

Now how do I convince GCL to do the right thing just like clisp does.
Is there some syntactical problem? As far as I know lambda definitions
are part of the Common Lisp hyperspec. Is GCL not fully compiant with
the spec or is the spec simply blurry on what should happen in the
above case?

Thanks,

Neil



Fri, 02 Apr 2004 09:06:28 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

> (defun apply-fun (f x) (f x))

(defun apply-fun (f x) (funcall f x))

Lisp, unlike Scheme, separates the "variable" from the "function" namespace.
Functions can live in variables, but they are still in the variable namespace.
Normal evaluation happens in the variable namespace.  FUNCALL is used to
call a function that is produced under normal (variable) evaluation.

The car of a form is ONLY permitted to be something you defined as a function
(usually by DEFUN, though also by SETF of SYMBOL-FUNCTION), or else a LAMBDA
expression.  Arbitrary forms for evaluate are not permitted directly in the
car of a form.  When you want that, just put FUNCALL in the car of the form
and the form you wanted in the car into the cadr.

Quote:
> (apply-fun plus-two 4) -> *** - EVAL: variable PLUS-TWO has no value

This is the reverse problem.  A function defined in the function namespace
is not a variable.  To move something from the function namespace to the
variable namespace, use the special operator FUNCTION.  
 (apply-fun (function plus-two) 4)
Though usually we use the shorthand notation
 (apply-fun #'plus-two 4)

Quote:
> I also tried the following, but I got the same error.

> (defun apply-fun (f x) (apply f (cons x NIL)))

You could have said (list x) instead of (cons x nil) here.
(apply f (list x)) is the same as (funcall f x).
So that would have worked if you'd gotten that far.  But you still
have to say
 (apply-fun #'plus-two 4)
to get far enough to see that this change of yours solved your first
problem above.  Use FUNCALL if you can, rather than APPLY as you have
done here, so you don't have to cons the spurious (list x).

Quote:
> Is there a way I can tell lisp that f is a function and not a variable?

#'f

Quote:
> Once I get this to work I should be able to write more complicated functions
> which take functions in the parameter list. Any ideas of what might have
> gone wrong in the definition of apply-fun ?

You were either taught by someone who knows Scheme rather than Lisp
or else you were just guessing at the semantics.  It helps to read a
document that tells you how things work.

If you get some time, read the description of the Lisp evaluator in
CLHS.
 http://www.xanalys.com/software_tools/reference/HyperSpec/FrontMatter/



Fri, 02 Apr 2004 10:40:36 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

> Common Lisp has two namespaces: The "regular" one, and one for
> functions (and other operators). The first position in a list form
> (meaning a list to be evaluated, like "(plus-one 3)") automatically
> uses the operator namespace, whereas the other positions uses the
> regular namespace.


> > Do I really have to use apply here or is there another way so that I
> > don't have to cons x into NIL?

> Your problem is that you have a function located in the regular
> namespace, and you want to call it. The function FUNCALL exists for
> this purpose. It accepts a function name (or an actual function
> object), looks it up in the operator namespace, and applies it to the
> rest of the arguments passed to it. (funcall 'plus-one 3) => 4.

Don't use 'plus-one if you can help it.  Prefer #'plus-one.

The two are slightly different.  'plus-one is a symbol, and symbols are
coerced by getting the globally defined function definition.  #'plus-one
is a special operator that gets the innermost lexically bound function
named plus-one, which is almost usually what you want.  e.g.,
 (flet ((add1 (x) (+ x 1)))
   (foo #'add1))
will work but
 (flet ((add1 (x) (+ x 1)))
   (foo 'add1))
will lose because it will look for a globally defined ADD1 instead of finding
the lexically bound ADD1.



Fri, 02 Apr 2004 10:43:06 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

>Is there a way I can tell lisp that f is a function and not a variable?

By passing a function object in the call, created using the (function ...)
special operator, and by calling that function object using funcall
or apply. The shorthand #'<form> is often used instead of
(function <form>) in idiomatic Lisp.

        (defun apply-function (f x) (funcall f x))

        (function-takes-function #'car '(42 43))
        ===> 42

Of course, it should be apparent that, apply-function is a completely
useless wrapper for funcall, since the caller can just use it directly:

        (funcall #'car '(42 43))

By the way, you must use funcall or apply. You cannot just write (f x),
because Lisp has special evaluation rules for the leftmost position of
a form, and because symbols have separate function and value bindings.
When you evaluate (f x), then the symbol f must have a function binding.
A binding to a function-object, like #'car is not a function binding,
but a value binding.



Fri, 02 Apr 2004 11:13:05 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

> (defun apply-fun (f x) (funcall f x))

> Lisp, unlike Scheme, separates the "variable" from the "function" namespace.
> Functions can live in variables, but they are still in the variable namespace.
> Normal evaluation happens in the variable namespace.  FUNCALL is used to
> call a function that is produced under normal (variable) evaluation.

Thanks for your explanation. The funcall construct is really useful when
you want to apply a function passed to a procedure as a variable in the
argument list to a single element within that procedure. Alternatively
one can use mapcar to apply such a function to a list of arguments to
obtain the list of componentwise evaluated arguments.

Quote:
> The car of a form is ONLY permitted to be something you defined as a function
> (usually by DEFUN, though also by SETF of SYMBOL-FUNCTION), or else a LAMBDA
> expression.  Arbitrary forms for evaluate are not permitted directly in the
> car of a form.  When you want that, just put FUNCALL in the car of the form
> and the form you wanted in the car into the cadr.

If this were correct then why is it that
the following does not work with GCL:

GCL> (funcall (lambda (x) (+ x 1)) '9)
Error: The function LAMBDA is undefined.
Fast links are on: do (si::use-fast-links nil) for debugging
Error signalled by EVAL.
Broken at FUNCALL.  Type :H for Help.

??? Is this a bug in GCL ???

CLISP> (funcall (lambda (x) (+ x 1)) '9)
10

It seems to me as though GCL is having some problems interpreting the
lambda notation but it does work when funcall is not used as in the
following example:

GCL> ((lambda (x) (+ x 1)) '9)
10

Quote:
>  http://www.xanalys.com/software_tools/reference/HyperSpec/FrontMatter/

Thanks for pointing me to the Common Lisp HyperSpec. This seems to be the
standard reference for ANSI Common Lisp.

Thanks,

Neil



Fri, 02 Apr 2004 11:29:46 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

> GCL> (funcall (lambda (x) (+ x 1)) '9)
> Error: The function LAMBDA is undefined.
> Fast links are on: do (si::use-fast-links nil) for debugging
> Error signalled by EVAL.
> Broken at FUNCALL.  Type :H for Help.

> ??? Is this a bug in GCL ???

Yes. GCL is not a little out of date as far as conformace to the
standard goes.

The expression works in CLISP because in Common Lisp there are both
special form "lambda" and macro "lamda", which expands to (function
(lambda ...)), which is the same as #'(lambda ...).

--
Janis Dzerins

  Eat shit -- billions of flies can't be wrong.



Fri, 02 Apr 2004 17:50:18 GMT  
 Common Lisp: passing a function to a function and applying it

Quote:

> Now how do I convince GCL to do the right thing just like clisp does.
> Is there some syntactical problem? As far as I know lambda definitions
> are part of the Common Lisp hyperspec. Is GCL not fully compiant with
> the spec or is the spec simply blurry on what should happen in the
> above case?

GCL is not compliant.

You can probably do this though (this code is *also* not compliant, but
I think it will work in GCL):

(defmacro lambda (args &body body)

--tim



Fri, 02 Apr 2004 18:44:55 GMT  
 
 [ 26 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Help: passing functions as arguments in Common Lisp

2. Passing variables to user functions of Clipper functions

3. Can We Pass Block from Function to Function?

4. math: passing function to function

5. F77-C: Passing Fortran FUNCTION as an argument for a C Function

6. Passing functions CONTAINed in a subroutine to other functions

7. Passing array valued functions as argument to function.

8. Common Lisp functions for Scheme?

9. List of all Common Lisp functions?

10. Common Lisp Hyperspec, Functions & Typechecking

11. Foreign function interfaces in Common Lisps

12. Common LISP Program/Function Archives

 

 
Powered by phpBB® Forum Software