Hi,
I am a newbie inLisp, and thought I could try things that would be
hard in other languages. I am trying to write a composer function.
That is, it takes a list of functions f1, f2, f3, ... fn and returns a
function that does, in regular math notation, f1 (f2 (f3 ...
(fn))...).
Here is my code, but evidently, I am not too good with the Lisp
syntax. Any pointers would be greatly appreciated. Of course, I
thought I would try the single argument lambda on the function first,
and then use the &rest there too (and find out if it works). Thanks in
advance!
Regards,
SK
Code:
(defun my-compose (&rest function-list)
(if (= 1 (length function-list))
#'(lambda(x) (funcall (car function-list) x))
#'(lambda(x) (funcall (car function-list) (funcall (my-
compose (cdr function-list)) x)))))
Invocation to compose the compound function:
(setf b (my-compose (list #'sin #'cos)))
Invocation to use it:
(funcall b 0.5)
I get an error message. BTW, I am using Emacs SLIME, which I believe
is Common Lisp.
From: Dimiter "malkia" Stanev
Subject: Re: Newbie question: writing a composer function in Lisp
Date:
Message-ID: <5lboubF7gcmcU1@mid.individual.net>
Hi,
> Code:
> (defun my-compose (&rest function-list)
> (if (= 1 (length function-list))
> #'(lambda(x) (funcall (car function-list) x))
> #'(lambda(x) (funcall (car function-list) (funcall (my-
> compose (cdr function-list)) x)))))
>
If you change car to caar, it would work:
(defun my-compose (&rest function-list)
(if (= 1 (length function-list))
#'(lambda(x) (funcall (caar function-list) x))
#'(lambda(x) (funcall (caar function-list)
(funcall (my-compose (cdr function-list)) x)))))
But it won't be correct.
The problem is that you are using (&rest function-list), which would
would put all the rest arguments in list itself, and that's why you need
double car - caar.
In fact, you don't need (&rest function-list), so the correct solution is:
(defun my-compose (function-list)
(if (= 1 (length function-list))
#'(lambda(x) (funcall (car function-list) x))
#'(lambda(x) (funcall (car function-list)
(funcall (my-compose (cdr function-list)) x)))))
Thanks,
Dimiter "malkia" Stanev.
In article <························@z24g2000prh.googlegroups.com>,
·········@hotmail.com wrote:
> Hi,
>
> I am a newbie inLisp, and thought I could try things that would be
> hard in other languages. I am trying to write a composer function.
> That is, it takes a list of functions f1, f2, f3, ... fn and returns a
> function that does, in regular math notation, f1 (f2 (f3 ...
> (fn))...).
>
> Here is my code, but evidently, I am not too good with the Lisp
> syntax. Any pointers would be greatly appreciated. Of course, I
> thought I would try the single argument lambda on the function first,
> and then use the &rest there too (and find out if it works). Thanks in
> advance!
>
> Regards,
>
> SK
>
> Code:
> (defun my-compose (&rest function-list)
> (if (= 1 (length function-list))
Simpler: (if (null (cdr function-list))
This doesn't require counting the length of the list on each recursion.
> #'(lambda(x) (funcall (car function-list) x))
This is equivalent to (car function-list).
> #'(lambda(x) (funcall (car function-list) (funcall (my-
> compose (cdr function-list)) x)))))
In your recursive call, you're passing a list of functions as a single
argument, rather than spreading them out as an &rest argument. You need
to use APPLY:
#'(lambda (x) (funcall (car function-list)
(funcall (apply #'my-compose (cdr function-list))
x)))
>
> Invocation to compose the compound function:
> (setf b (my-compose (list #'sin #'cos)))
>
> Invocation to use it:
> (funcall b 0.5)
>
> I get an error message. BTW, I am using Emacs SLIME, which I believe
> is Common Lisp.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
·········@hotmail.com wrote:
> Code:
> (defun my-compose (&rest function-list)
> (if (= 1 (length function-list))
> #'(lambda(x) (funcall (car function-list) x))
> #'(lambda(x) (funcall (car function-list) (funcall (my-
> compose (cdr function-list)) x)))))
>
> Invocation to compose the compound function:
> (setf b (my-compose (list #'sin #'cos)))
>
> Invocation to use it:
> (funcall b 0.5)
This should fix it (borrowing from Barry's reply):
(defun my-compose (&rest function-list)
(if (cdr function-list)
(lambda (x)
(funcall (car function-list)
(funcall (apply 'my-compose (cdr function-list)) x)))
(lambda (x)
(funcall (car function-list) x))))
(funcall (my-compose 'sqrt 'sqrt) 16)
Here's another variant of compose.
(defun compose (f &optional (g f))
(lambda (x)
(funcall f (funcall g x))))
(funcall (compose 'sqrt) 16)
FWIW, multiple compositions might be worth a macro...
> I get an error message. BTW, I am using Emacs SLIME, which I believe
> is Common Lisp.
Nitpick: Slime is an editing environment that attaches to Lisp;
(lisp-implementation-type) and (lisp-implementation-version) should
tell you which one its using.
OT: For kicks, try (describe 'my-compose).
- Daniel