Hello lispers,
I want to write a function RETURN-G, that takes as argument a function
F of NF arguments and a value V. I want to return it a new function G
of NG=(NF-1) arguments and is defined as
(G X X ... X ) = (F V X X ... X ).
1 2 NG 1 2 NG
I tried it as following :
(defun return-g (f v)
#'(lambda (&rest l)
(apply #'f (append (list v) l))))
=> return-g
Now it is possible to do :
(defun f (x1 x2 x3) (+ x1 x2 x3))
=> f
(setf g (return-g #'f 0))
=> g
(funcall g 1 2)
=> 3
which is correct, but I can't seem to get (g 1 2) working :
(g 1 2)
=> Error: Non-symbol used as a lambda argument name
in function G. [condition type: PROGRAM-ERROR]
However, it should be possible I think.
Anyone else thinks so too ? (and has a sollution :)
Thanks !
--
Joachim De Beule,
tel: +32 9 2646541
email: ·······@inwpent3.rug.ac.be
joachim de beule <·······@inwpent3.rug.ac.be> a �crit :
> (setf g (return-g #'f 0))
Should be: (setf (symbol-function 'g) (return-g #'f 0))
--
Georges KO, Namur (Belgique) Alcatel Telecom Taiwan ···@gko.net
D�cade II, Sextidi de Pluvi�se de l'Ann�e 207 de la R�volution
joachim de beule <·······@inwpent3.rug.ac.be> writes:
> I want to write a function RETURN-G, that takes as argument a function
> F of NF arguments and a value V.
I hope I don't end up answering some homework here, since this looks
suspiciously like a homework problem. On the other hand, your program
logic looks right and it looks like you're only tripping up on tiny
differences in syntax between Common Lisp and either Scheme or the
Lambda Calculus, whatever motivated this thing, so I'm going to speak
pretty directly to the solution because I don't see any way to avoid
it, and because I think that will still be most instructive.
> I want to return it a new function G
> of NG=(NF-1) arguments and is defined as
>
> (G X X ... X ) = (F V X X ... X ).
> 1 2 NG 1 2 NG
>
> I tried it as following :
>
> (defun return-g (f v)
> #'(lambda (&rest l)
> (apply #'f (append (list v) l))))
> => return-g
>
> Now it is possible to do :
>
> (defun f (x1 x2 x3) (+ x1 x2 x3))
> => f
> (setf g (return-g #'f 0))
> => g
> (funcall g 1 2)
> => 3
>
> which is correct,
But is only accidentally correct because you have defined an external
function F and then referred to the external function directly by name
within the definition of the function. That is, had you defined:
(defun return-g (z v)
#'(lambda (&rest l)
(apply #'f (append (list v) l))))
you would have gotten the same result because the #'f refers to the
functional binding of F, not the variable binding of F, and in both your
version and the version I've written, you've not bound the functional F.
Had you written this correctly, you would have had the key in hand to
how to answer the question you were asking. What you want is:
(defun return-g (z v)
#'(lambda (&rest l)
(apply z (append (list v) l))))
Note the absence of the #' before the use of Z because it's the variable
binding of Z we want to apply, not the function binding. Had I said
#'z, I would have been using a global function definition.
- - - - -
However, also note that the idiom
(apply function (APPEND (LIST value1 value2 ...) list))
or (apply function (CONS value1 list))
or (apply function (LIST* value1 value2 ... list))
are each better written in Common Lisp as:
(apply function value1 value2 ... list)
since APPLY is nary in Common Lisp and only its last argument is spread.
In practice, the values will often be copied onto a stack before the APPLY,
so it's better to let the implementation do the consing of a list if it's
needed, but you shouldn't assume it will be needed.
So
#'(lambda (&rest l)
(apply z v l))
rather than
#'(lambda (&rest l)
(apply z (append (list v) l)))
On the other hand, if there were multiple elements in the list
which you have given here as (LIST v), then you might not be
able to avoid the APPEND. e.g.,
(defun curry (original-function &rest some-of-its-args)
#'(lambda (&rest the-rest-of-its-args)
(apply original-function
(append some-of-its-args
the-rest-of-its-args))))
- - - - -
Note also that the function name return-g is suspect since if you're
going to "return" the function, it needn't have a given name. It's
good to name things according to what they do. You might want to call
this function CURRY for example, since that's what it does. Or
BIND-ARGUMENT. Or something that has a functional feel. Small point.
- - - - -
> but I can't seem to get (g 1 2) working :
>
> (g 1 2)
> => Error: Non-symbol used as a lambda argument name
> in function G. [condition type: PROGRAM-ERROR]
>
> However, it should be possible I think.
> Anyone else thinks so too ? (and has a sollution :)
The answer here is the same as it was for the other question I answered
above. You're using the function binding when you should be using
the variable binding. Since you SETF'd G, you have the value in the
variable G. Georges Ko has suggested you might set the
(symbol-function 'g) but he is presuming that you really wanted to
set the G function. I am here alleging that you should not, as a rule,
have Common Lisp functions that dynamically assign function definitions
except during the bootstrapping of a system. I consider it bad style
for reasons to messy to go into here. Instead, I suggest you really do
as you had done and use
(SETQ G (CURRY #'F 0))
(FUNCALL G 1 2)
That is, rather than put the value some other place, you should get
the value from the place you put it.
Good luck.
--Kent
N.B. I didn't try any of the stuff I said above in an actual implementation.
My net connection is such that the Emacs I'm typing to isn't on the
same machine as the various Lisp implementations I have, and it's
tedious to do so. So if something doesn't work, it may be my bug.
But hopefully I've given you enough clues to allow you to blunder ahead.
Kent M Pitman <······@world.std.com> writes:
> I hope I don't end up answering some homework here, since this looks
> suspiciously like a homework problem. On the other hand, your program
> logic looks right and it looks like you're only tripping up on tiny
> differences in syntax between Common Lisp and either Scheme or the
> Lambda Calculus, whatever motivated this thing, so I'm going to speak
> pretty directly to the solution because I don't see any way to avoid
> it, and because I think that will still be most instructive.
No it is not part of some homework. I just 'rephrased' my problem
in order to get to the hart of it. (I'm not actually working with
functions RETURN-G, F or G.)
> N.B. I didn't try any of the stuff I said above in an actual implementation.
> My net connection is such that the Emacs I'm typing to isn't on the
> same machine as the various Lisp implementations I have, and it's
> tedious to do so. So if something doesn't work, it may be my bug.
> But hopefully I've given you enough clues to allow you to blunder ahead.
It was indeed very instructive !! ... and, apart from saving you from some
sleepless nights with respect to the 'homework-issue', I just wanted to
thank you for your reply.
Thanks !
--
Joachim De Beule,
tel: +32 9 2646541
email: ·······@inwpent3.rug.ac.be
joachim de beule <·······@inwpent3.rug.ac.be> writes:
>
> (defun return-g (f v)
> #'(lambda (&rest l)
> (apply #'f (append (list v) l))))
There are two issues with the line above. The first is that you are
using a constant function #'f in the apply, so that if you were to call
something like (return-g #'g 2) you would still apply #'f and not #'g.
The solution (which might also eliminate some gratuitous consing) is
(apply f v l) ))
> => return-g
--
Thomas A. Russ, USC/Information Sciences Institute ···@isi.edu