From: Dr. Mirko Luedde
Subject: newbie: function composition
Date: 
Message-ID: <38E0640B.25ABD137@Computer.Org>
Hi there, 

given two functions, F1 and F2, I would like 
to compute the composition F1 o F2. 
My naive approach fails: 

	( defun composition ( F1 F2 ) 
  	"Compose the function F1 with F2 to yield the function (F1 o F2)."
	  ( lambda ( x ) ( F1 ( F2 x ) ) ) )

The arguments "F1" and "F2" don't find their 
way into the function definition body. 
Indeed, the expression 

	( composition '1+ '1+ )

evaluates to 

	(lambda (x) (F1 (F2 x)))

instead of 

	(lambda (x) (1+ (1+ x)))

I'm surely missing a basic point here. Could someone 
please shed some light on it? 

Cheers, 
-- 
Mirko Luedde (············@Computer.Org)

From: Dr Nick Levine
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E0706D.9D5A59AD@beta.csd.anglia.ac.uk>
"Dr. Mirko Luedde" wrote:

> given two functions, F1 and F2, I would like
> to compute the composition F1 o F2.
> My naive approach fails:
> 
>         ( defun composition ( F1 F2 )
>         "Compose the function F1 with F2 to yield the function (F1 o F2)."
>           ( lambda ( x ) ( F1 ( F2 x ) ) ) )
> 
> The arguments "F1" and "F2" don't find their
> way into the function definition body.


(defun compose (fn1 fn2)
  #'(lambda (&rest args)
      (funcall fn1 (apply fn2 args))))

It always struck me that there is a hidden catch (or maybe, a lack of
grace) in this mode of thinking though - fn2 can have as many arguments
as it likes, but fn1 is assumed to take just one argument (and fn2 to
return just one). Of course, you can always hack up a multiple-value
version of the above, but somehow that's never what anybody wanted.

- n
From: Tim Bradshaw
Subject: Re: newbie: function composition
Date: 
Message-ID: <ey37len72wu.fsf@cley.com>
* Nick Levine wrote:

> (defun compose (fn1 fn2)
>   #'(lambda (&rest args)
>       (funcall fn1 (apply fn2 args))))

> It always struck me that there is a hidden catch (or maybe, a lack of
> grace) in this mode of thinking though - fn2 can have as many arguments
> as it likes, but fn1 is assumed to take just one argument (and fn2 to
> return just one). Of course, you can always hack up a multiple-value
> version of the above, but somehow that's never what anybody wanted.

Though I see your point, I'm not sure why you write it like this --
I'd write it as (lambda (x) (funcall f1 (funcall f2 x))), which at
least consistently expects one argument / one return value?

--tim
From: Dr Nick Levine
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E0C07F.72C8F5F5@beta.csd.anglia.ac.uk>
Tim Bradshaw wrote:

> Though I see your point, I'm not sure why you write it like this --
> I'd write it as (lambda (x) (funcall f1 (funcall f2 x))), which at
> least consistently expects one argument / one return value?

Because it hides the issue altogether? ;-)

- n
From: Paul Rudin
Subject: Re: newbie: function composition
Date: 
Message-ID: <wkpusfm7kf.fsf@scientia.com>
>>>>> "Tim" == Tim Bradshaw <···@cley.com> writes:

 Tim> * Nick Levine wrote:
 >> (defun compose (fn1 fn2) #'(lambda (&rest args) (funcall fn1 (apply fn2
 >> args))))

 >> It always struck me that there is a hidden catch (or maybe, a lack of
 >> grace) in this mode of thinking though - fn2 can have as many arguments
 >> as it likes, but fn1 is assumed to take just one argument (and fn2 to
 >> return just one). Of course, you can always hack up a multiple-value
 >> version of the above, but somehow that's never what anybody wanted.

 Tim> Though I see your point, I'm not sure why you write it like this --
 Tim> I'd write it as (lambda (x) (funcall f1 (funcall f2 x))), which at
 Tim> least consistently expects one argument / one return value?

What about?


(defun compose2fns (f1 f2)
   #'(lambda (&rest args) (funcall f1 (apply f2 args))))

(defun compose (&rest fns)   
  (reduce #'compose2fns fns 
          :initial-value 
          #'(lambda (&rest args) 
              (values-list args))
          :from-end t))
From: Mirko Luedde
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E11A56.1C5811F0@Computer.Org>
Paul, I'm sorry to say, same problem as with all the rest: 

  (defun compose2fns (f1 f2)
     #'(lambda (&rest args) (funcall f1 (apply f2 args))))
  compose2fns
  ( compose2fns #'1+ #'1+ )
  (lambda (&rest args) (funcall f1 (apply f2 args)))

Thanks, Mirko. 

Paul Rudin wrote:
> 
> >>>>> "Tim" == Tim Bradshaw <···@cley.com> writes:
> 
>  Tim> * Nick Levine wrote:
>  >> (defun compose (fn1 fn2) #'(lambda (&rest args) (funcall fn1 (apply fn2
>  >> args))))
> 
>  >> It always struck me that there is a hidden catch (or maybe, a lack of
>  >> grace) in this mode of thinking though - fn2 can have as many arguments
>  >> as it likes, but fn1 is assumed to take just one argument (and fn2 to
>  >> return just one). Of course, you can always hack up a multiple-value
>  >> version of the above, but somehow that's never what anybody wanted.
> 
>  Tim> Though I see your point, I'm not sure why you write it like this --
>  Tim> I'd write it as (lambda (x) (funcall f1 (funcall f2 x))), which at
>  Tim> least consistently expects one argument / one return value?
> 
> What about?
> 
> (defun compose2fns (f1 f2)
>    #'(lambda (&rest args) (funcall f1 (apply f2 args))))
> 
> (defun compose (&rest fns)
>   (reduce #'compose2fns fns
>           :initial-value
>           #'(lambda (&rest args)
>               (values-list args))
>           :from-end t))

-- 
Dr. Mirko Luedde (············@Computer.Org)
From: Mirko Luedde
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E1199B.5D94970B@Computer.Org>
Thanks Tim, 

but same problem as with Nick's proposal, see my emacs session: 

  (defun compose (fn1 fn2)
    #'(lambda (x)
        (funcall fn1 (apply fn2 x))))
  compose
  ( compose #'1+ #'1+ )
  (lambda (x) (funcall fn1 (apply fn2 x)))

What's up here? 

Yours, Mirko. 

Tim Bradshaw wrote:
> 
> * Nick Levine wrote:
> 
> > (defun compose (fn1 fn2)
> >   #'(lambda (&rest args)
> >       (funcall fn1 (apply fn2 args))))
> 
> > It always struck me that there is a hidden catch (or maybe, a lack of
> > grace) in this mode of thinking though - fn2 can have as many arguments
> > as it likes, but fn1 is assumed to take just one argument (and fn2 to
> > return just one). Of course, you can always hack up a multiple-value
> > version of the above, but somehow that's never what anybody wanted.
> 
> Though I see your point, I'm not sure why you write it like this --
> I'd write it as (lambda (x) (funcall f1 (funcall f2 x))), which at
> least consistently expects one argument / one return value?
> 
> --tim

-- 
Dr. Mirko Luedde (············@Computer.Org)
From: Barry Margolin
Subject: Re: newbie: function composition
Date: 
Message-ID: <rc9E4.39$5p5.1353@burlma1-snr2>
In article <·················@Computer.Org>,
Mirko Luedde  <············@Computer.Org> wrote:
>Thanks Tim, 
>
>but same problem as with Nick's proposal, see my emacs session: 
>
>  (defun compose (fn1 fn2)
>    #'(lambda (x)
>        (funcall fn1 (apply fn2 x))))
>  compose
>  ( compose #'1+ #'1+ )
>  (lambda (x) (funcall fn1 (apply fn2 x)))
>
>What's up here? 

How many times are you going to post that same piece of code?

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Yuan
Subject: Re: newbie: function composition
Date: 
Message-ID: <60n1nj9jgt.fsf@laffytaffy.cs.umd.edu>
Dr Nick Levine <·······@beta.csd.anglia.ac.uk> writes:

> (defun compose (fn1 fn2)
>   #'(lambda (&rest args)
>       (funcall fn1 (apply fn2 args))))
> 
> It always struck me that there is a hidden catch (or maybe, a lack of
> grace) in this mode of thinking though - fn2 can have as many arguments
> as it likes, but fn1 is assumed to take just one argument (and fn2 to
> return just one). Of course, you can always hack up a multiple-value
> version of the above, but somehow that's never what anybody wanted.

How are the multiple values to be computed then?  Of course, each by a
separate function:

(defun composition (g &rest h)
  "f(y) = g(h1(y), ..., hn(y))."
  #'(lambda (&rest y)
      (apply g (mapcar #'(lambda (hi)
			   (apply hi y))
		       h))))

That is the definition used by most computation theorists.  The other
two building blocks of recursive functions:

(defun primitive-recursion (g h)
  "f(x, y) =
     g(y)                  if x = 0;
     h(f(x-1, y), x-1, y)  otherwise."
  #'(lambda (&rest z)
      (destructuring-bind (x . y) z
	(if (zerop x)
	    (apply g y)
	    (apply h
		   (apply f (1- x) y)
		   (1- x)
		   y)))))

(defun mu-recursion (g)
  "f(y) = \mu_x[g(x, y) = 0]."
  #'(lambda (&rest y)
      (do ((x 0 (1+ x)))
	  ((zerop (apply g x y)) x))))
From: Fernando D. Mato Mira
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E0F150.4B6E2128@iname.com>
Yuan wrote:

> How are the multiple values to be computed then?  Of course, each by a
> separate function:

Only Marco is allowed to make jokes in this newsgroup! ;)

--
Fernando D. Mato Mira
Real-Time SW Eng & Networking
Advanced Systems Engineering Division
CSEM
Jaquet-Droz 1                   email: matomira AT acm DOT org
CH-2007 Neuchatel                 tel:       +41 (32) 720-5157
Switzerland                       FAX:       +41 (32) 720-5720

www.csem.ch      www.vrai.com     ligwww.epfl.ch/matomira.html
From: Will Deakin
Subject: Re: newbie: function composition
Date: 
Message-ID: <8brcun$sr3$1@epos.tesco.net>
Fernando D. Mato Mira wrote
>Only Marco is allowed to make jokes in this newsgroup! ;)
I'm sure what you really mean is: `Only Marco is allowed to make jokes as bad as
this in this newsgroup!'

 ;) will
From: Marco Antoniotti
Subject: Re: newbie: function composition
Date: 
Message-ID: <lw66u62nps.fsf@parades.rm.cnr.it>
"Will Deakin" <···········@hotmail.com> writes:

> Fernando D. Mato Mira wrote
> >Only Marco is allowed to make jokes in this newsgroup! ;)
> I'm sure what you really mean is: `Only Marco is allowed to make jokes as bad as
> this in this newsgroup!'
> 

Do you mean that I should make better jokes? :)

Cheers

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - 06 68 10 03 17, fax. +39 - 06 68 80 79 26
http://www.parades.rm.cnr.it/~marcoxa
From: William Deakin
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E1D82E.9A37368A@pindar.com>
Marco wrote:

> Do you mean that I should make better jokes? :)

No, that maybe I should ;)

Cheers,

:) will
From: Fernando D. Mato Mira
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E1D69C.10E377B8@iname.com>
Will Deakin wrote:

> Fernando D. Mato Mira wrote
> >Only Marco is allowed to make jokes in this newsgroup! ;)
> I'm sure what you really mean is: `Only Marco is allowed to make jokes as bad as
> this in this newsgroup!'

I was sure you were going to follow up ;->

That was not a joke. It said:

(defun compose (fn1 fn2)
  #'(lambda (&rest args)
      (declare (dynamic-extent args))
      (multiple-value-call fn1 (apply fn2 args))))

Learn to read ;)

--
Fernando D. Mato Mira
Real-Time SW Eng & Networking
Advanced Systems Engineering Division
CSEM
Jaquet-Droz 1                   email: matomira AT acm DOT org
CH-2007 Neuchatel                 tel:       +41 (32) 720-5157
Switzerland                       FAX:       +41 (32) 720-5720

www.csem.ch      www.vrai.com     ligwww.epfl.ch/matomira.html
From: William Deakin
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E1D919.8048724B@pindar.com>
Fernando wrote:

> Will wrote:
>
> I was sure you were going to follow up ;->

Baiting me eh? Well I fell for it, so you got me :|

> Learn to read ;)

Thanks for the advice. I'll try to fit it into my busy schedule ;)

(I think my newsfeed let me down and I'm missing some parts of this thread. Or I could
just be missing something, like good sense, intelligence, or as you pointed out, the
ability to read and compile lisp code in my head &c),

Cheers,

:) will
From: Rahul Jain
Subject: Re: newbie: function composition
Date: 
Message-ID: <8bsnjo$sjm$1@joe.rice.edu>
In article <·················@pindar.com> posted on Wednesday, March 29,
2000  4:17 AM, William Deakin <·····@pindar.com> wrote:

> (I think my newsfeed let me down and I'm missing some parts of this thread. Or I could
> just be missing something, like good sense, intelligence, or as you pointed out, the
> ability to read and compile lisp code in my head &c),
> 
> Cheers,
> 
> :) will
> 
> 
> 

The lag time from Europe has been on the order of a day or two here...
sometimes more...

-- 
-> -\-=-=-=-=-=-=-=-=-=-/^\-=-=-=<*><*>=-=-=-/^\-=-=-=-=-=-=-=-=-=-/- <-
-> -/-=-=-=-=-=-=-=-=-=/ {  Rahul -<>- Jain   } \=-=-=-=-=-=-=-=-=-\- <-
-> -\- "I never could get the hang of Thursdays." - HHGTTG by DNA -/- <-
-> -/- http://photino.sid.rice.edu/ -=- ·················@usa.net -\- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   Version 11.423.999.210020101.23.50110101.042
   (c)1996-2000, All rights reserved. Disclaimer available upon request.
From: Mirko Luedde
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E118F8.70D3C239@Computer.Org>
Thanks Nick, 

but the problem remains. An exception from my emacs session: 

  (defun compose (fn1 fn2)
    #'(lambda (&rest args)
        (funcall fn1 (apply fn2 args))))
  compose
  ( compose '1+ '1+ )
  (lambda (&rest args) (funcall fn1 (apply fn2 args)))

Where do the "fn1", "fn2" come from in the evaluation 
of "( compose '1+ '1+ )"?

Cheers, Mirko.

Dr Nick Levine wrote:
> 
> "Dr. Mirko Luedde" wrote:
> 
> > given two functions, F1 and F2, I would like
> > to compute the composition F1 o F2.
> > My naive approach fails:
> >
> >         ( defun composition ( F1 F2 )
> >         "Compose the function F1 with F2 to yield the function (F1 o F2)."
> >           ( lambda ( x ) ( F1 ( F2 x ) ) ) )
> >
> > The arguments "F1" and "F2" don't find their
> > way into the function definition body.
> 
> (defun compose (fn1 fn2)
>   #'(lambda (&rest args)
>       (funcall fn1 (apply fn2 args))))
> 
> It always struck me that there is a hidden catch (or maybe, a lack of
> grace) in this mode of thinking though - fn2 can have as many arguments
> as it likes, but fn1 is assumed to take just one argument (and fn2 to
> return just one). Of course, you can always hack up a multiple-value
> version of the above, but somehow that's never what anybody wanted.
> 
> - n

-- 
Dr. Mirko Luedde (············@Computer.Org)
From: Barry Margolin
Subject: Re: newbie: function composition
Date: 
Message-ID: <9b9E4.38$5p5.1205@burlma1-snr2>
In article <·················@Computer.Org>,
Mirko Luedde  <············@Computer.Org> wrote:
>Thanks Nick, 
>
>but the problem remains. An exception from my emacs session: 
>
>  (defun compose (fn1 fn2)
>    #'(lambda (&rest args)
>        (funcall fn1 (apply fn2 args))))
>  compose
>  ( compose '1+ '1+ )
>  (lambda (&rest args) (funcall fn1 (apply fn2 args)))
>
>Where do the "fn1", "fn2" come from in the evaluation 
>of "( compose '1+ '1+ )"?

You can't do this in Emacs Lisp.  It only works in a Lisp with lexical
closures.

You can use cl.el's lexical-let to emulate it:

(defun compose (fn1 fn2)
  (lexical-let ((lexical-f1 fn1)
                (lexical-f2 fn2))
    #'(lambda (&rest args)
        (funcall lexical-f1 (apply lexical-f2 args)))))
compose
(compose '1+ '1+)
(lambda (&rest --cl-rest--)
  (apply (quote (lambda (G97912 G97913 &rest args)
                  (funcall (symbol-value G97913)
                           (apply (symbol-value G97912) args))))
         (quote --lexical-f2--) (quote --lexical-f1--) --cl-rest--))
(funcall (compose '1+ '1+) 3)
5

You might want to put the lexical-let expression through macroexpand to see
how it simulates a closure.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Thomas A. Russ
Subject: Re: newbie: function composition
Date: 
Message-ID: <ymivh26vebf.fsf@sevak.isi.edu>
Mirko Luedde <············@Computer.Org> writes:

> but the problem remains. An exception from my emacs session: 

Ahhh.  Does this mean that you are using Emacs Lisp?  If so, then that
would explain the problem.  Most people on this list (including myself)
assume that Common Lisp as the default lisp dialect.

>   (defun compose (fn1 fn2)
>     #'(lambda (&rest args)
>         (funcall fn1 (apply fn2 args))))
>   compose
>   ( compose '1+ '1+ )
>   (lambda (&rest args) (funcall fn1 (apply fn2 args)))
> 
> Where do the "fn1", "fn2" come from in the evaluation 
> of "( compose '1+ '1+ )"?

The difficulty is that Emacs lisp is dynamically scoped, not lexically
scoped.  Therefore, no closure around the lambda expression is
constructed -- so the variables fn1 and fn2 are treated as dynamic
(special) variables and are assumed to be bound.

Let's see if I get the direction straight:
This is a fairly well-known Lisp problem called the upward funarg
problem, where a function is returned out of an environment that binds
variables that the function depends on.

I would expect that in a dynamically scoped lisp like Emacs lisp that
you would need to construct the lambda expression explicitly (Does Emacs
lisp have backquote?), substituting the values of the variables into the
appropriate places.  If you have to do that, you can probably avoid the
need to use funcall as well:

(defun compose (fn1 fn2)
   (list 'lambda '(arg)
          (list fn1 (list fn2 'arg))))

(funcall (compose '1+ '1+) 2)   =>  4

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Alex Henderson
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E1928B.89FF67AB@hermes.cam.ac.uk>
> Ahhh.  Does this mean that you are using Emacs Lisp?  If so, then that
> would explain the problem.  Most people on this list (including myself)
> assume that Common Lisp as the default lisp dialect.

Indeed.

> (defun compose (fn1 fn2)
>    (list 'lambda '(arg)
>           (list fn1 (list fn2 'arg))))
> 
> (funcall (compose '1+ '1+) 2)   =>  4

This works with the copy of emacs I have, as does: (for a different approach)

(defmacro compose (f1 f2)
  `#'(lambda (x)
       (funcall ,f1 (funcall ,f2 x))))

- evidently backquote is defined in emacs lisp.

Some solution to the multiple-values/arguments issue might be:

(defmacro compmac (f1 f2)
  `#'(lambda (&rest args)
       (apply ,f1 (multiple-value-list (apply ,f2 args)))))

... but when emacs is presented with this we get:
'Symbol's function definition is void: multiple-value-list'

:-)

A (who likes writing all the #' explicitly, to make sure he knows what
things are doing...)

-- 
Barium: What you do with dead chemists.
From: Dave Pearson
Subject: Re: newbie: function composition
Date: 
Message-ID: <slrn8e3kfm.rfd.davep.news@hagbard.demon.co.uk>
On Wed, 29 Mar 2000 06:20:12 +0100, Alex Henderson <·····@hermes.cam.ac.uk> wrote:
> (defmacro compmac (f1 f2)
>   `#'(lambda (&rest args)
>        (apply ,f1 (multiple-value-list (apply ,f2 args)))))
> 
> ... but when emacs is presented with this we get:
> 'Symbol's function definition is void: multiple-value-list'

,----[ C-h f multiple-value-list RET ]
| multiple-value-list is an alias for `identity' in `cl'.
| 
| Return the argument unchanged.
| 
| (identity ARG)
`----

A (require 'cl) should give you what you're after.

-- 
Take a look in Hagbard's World: | festival.jl - Make sawmill talk.
http://www.hagbard.demon.co.uk/ |  keydrag.jl - Drag windows from keyboard.
http://www.acemake.com/hagbard/ |  sawmill.el - Sawmill mode for emacs.
sawmill software, including.....|  uptimes.jl - Record sawmill uptimes.
From: Tim Bradshaw
Subject: Re: newbie: function composition
Date: 
Message-ID: <ey3aejj76ui.fsf@cley.com>
* Mirko Luedde wrote:
> 	( defun composition ( F1 F2 ) 
>   	"Compose the function F1 with F2 to yield the function (F1 o F2)."
> 	  ( lambda ( x ) ( F1 ( F2 x ) ) ) )

Common Lisp has different namespaces for functions and variables, you
need to write:

(defun compose (f1 f2)
  (lambda (x)
    (funcall f1 (funcall f2 x))))

And then (say), (compose #'1+ #'1+)

--tim
From: Mirko Luedde
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E11B51.7EFF1266@Computer.Org>
Yo Tim, 

this results in the following emacs session: 

  (defun compose (f1 f2)
    (lambda (x)
      (funcall f1 (funcall f2 x))))
  compose
  (compose #'1+ #'1+)
  (lambda (x) (funcall f1 (funcall f2 x)))

Probably my problem is so basic that I should better 
have avoided posting it ... 

Regards, Mirko. 

Tim Bradshaw wrote:
> 
> * Mirko Luedde wrote:
> >       ( defun composition ( F1 F2 )
> >       "Compose the function F1 with F2 to yield the function (F1 o F2)."
> >         ( lambda ( x ) ( F1 ( F2 x ) ) ) )
> 
> Common Lisp has different namespaces for functions and variables, you
> need to write:
> 
> (defun compose (f1 f2)
>   (lambda (x)
>     (funcall f1 (funcall f2 x))))
> 
> And then (say), (compose #'1+ #'1+)
> 
> --tim

-- 
Dr. Mirko Luedde (············@Computer.Org)
From: Tim Bradshaw
Subject: Re: newbie: function composition
Date: 
Message-ID: <ey3g0ta65sd.fsf@cley.com>
* Mirko Luedde wrote:
> Yo Tim, 
> this results in the following emacs session: 

Use common Lisp or scheme or any other lisp that is less than 20 years
out of date.

--tim
From: Mirko Luedde
Subject: Re: newbie: function composition
Date: 
Message-ID: <38E11C52.580D46EB@Computer.Org>
Clemens, 

your Lisp session looks fine. My emacs session looks like this: 

  (defun composition (f1 f2)
              (lambda (x) (funcall f1 (funcall f2 x))))
  composition
  (funcall (composition #'1+ #'1+) 0)
   < Symbol's value as a variable is void: f1 >

I simply don't get it right. 

Sincerely, Mirko. 

Clemens Heitzinger wrote:
> 
> "Dr. Mirko Luedde" <············@Computer.Org> writes:
> 
> > Hi there,
> >
> > given two functions, F1 and F2, I would like
> > to compute the composition F1 o F2.
> > My naive approach fails:
> >
> >       ( defun composition ( F1 F2 )
> >       "Compose the function F1 with F2 to yield the function (F1 o F2)."
> >         ( lambda ( x ) ( F1 ( F2 x ) ) ) )
> >
> > The arguments "F1" and "F2" don't find their
> > way into the function definition body.
> > Indeed, the expression
> >
> >       ( composition '1+ '1+ )
> >
> > evaluates to
> >
> >       (lambda (x) (F1 (F2 x)))
> >
> > instead of
> >
> >       (lambda (x) (1+ (1+ x)))
> >
> > I'm surely missing a basic point here. Could someone
> > please shed some light on it?
> 
> First, you have to use FUNCALL in the definition of composition
> (contrary to Scheme).  Second, you have to discern between a symbol
> and the function it denotes:  '1+ means the symbol
> 1+, #'1+ means the function stored in the "function slot" of the
> symbol 1+.
> 
> USER(86): (defun composition (f1 f2)
>             (lambda (x) (funcall f1 (funcall f2 x))))
> COMPOSITION
> USER(87): (funcall (composition #'- #'-) 3)
> 3
> USER(88): (funcall (composition #'1+ #'1+) 3)
> 5
> USER(89): (symbol-function '1+)
> #<Function 1+>
> USER(90):
> 
> Yours,
> Clemens
> --
> Dipl-Ing Clemens Heitzinger
> Institute for Microelectronics, Vienna University of Technology, Austria
> Homepage <http://ag.or.at:8000/~clemens>   (Lisp related material)
> Mail <···············@ag.or.at>, Phone +43-1-58801/36035

-- 
Dr. Mirko Luedde (············@Computer.Org)
From: Hrvoje Niksic
Subject: Re: newbie: function composition
Date: 
Message-ID: <dpsnx9am91.fsf@mraz.iskon.hr>
Mirko Luedde <············@Computer.Org> writes:

> your Lisp session looks fine. My emacs session looks like this: 
> 
>   (defun composition (f1 f2)
>               (lambda (x) (funcall f1 (funcall f2 x))))
>   composition
>   (funcall (composition #'1+ #'1+) 0)
>    < Symbol's value as a variable is void: f1 >

Elisp is not lexically scoped, so the actual values of f1 and f2 get
lost by the time your lambda is invoked.  You can fake lexical scoping
by creating a lambda dynamically using backquotes:

(defun composition (f1 f2)
  `(lambda (x) (funcall ',f1 (funcall ',f2 x))))
  => composition
(funcall (composition #'1+ #'1+) 0)
  => 2

Or, if you're into CL extensions, you can use its `lexical-let'
feature to force f1 and f2 into being scoped lexically:

(require 'cl)
(defun composition (f1 f2)
  (lexical-let ((f1 f1) (f2 f2))
    (lambda (x) (funcall f1 (funcall f2 x)))))
  => composition
(funcall (composition #'1+ #'1+) 0)
  => 2
From: Sam Steingold
Subject: Re: newbie: function composition
Date: 
Message-ID: <u4s9phkk3.fsf@ksp.com>
>>>> In message <·················@Computer.Org>
>>>> On the subject of "newbie: function composition"
>>>> Sent on Tue, 28 Mar 2000 09:49:31 +0200
>>>> Honorable "Dr. Mirko Luedde" <············@Computer.Org> writes:
 >> 
 >> given two functions, F1 and F2, I would like 
 >> to compute the composition F1 o F2. 
 >> My naive approach fails: 
 >> 
 >> 	( defun composition ( F1 F2 ) 
 >>   	"Compose the function F1 with F2 to yield the function (F1 o F2)."
 >> 	  ( lambda ( x ) ( F1 ( F2 x ) ) ) )

this would have worked in scheme, but not in lisp, which requires
`funcall':

(defun c (f g) (lambda (x) (funcall f (funcall g x))))

you might want to look at the file ext.lsp in
http://www.podval.org/~sds/data/port.zip, which provides a macro
`compose' which will compose any number of functions and macros, and 2
functions: `compose-f', which can compose only functions of one arg and
`compose-all', which will feed all the return values of a function to
the next one. 


-- 
Sam Steingold (http://www.podval.org/~sds)
Micros**t is not the answer.  Micros**t is a question, and the answer is Linux,
(http://www.linux.org) the choice of the GNU (http://www.gnu.org) generation.
It's not just a language, it's an adventure.  Common Lisp.