From: Rob Warnock
Subject: Re: combination of applications
Date: 
Message-ID: <fcidnROznq2IZFHd4p2dnA@speakeasy.net>
Stefan Ram <···@zedat.fu-berlin.de> wrote:
+---------------
|   Are there means in Lisp with the same effect, possibly
|   something like the following?
| ( combine f g h x )
+---------------

Do a Web search for the terms COMPOSE and/or CURRY. Note that if
any of the functions but the last one take more than one argument,
you will need to CURRY that function with N-1 arguments before
COMPOSE'ing it.

For non-associative functions, you sometimes need CURRY-RIGHT and
CURRY-LEFT variations, as well as pattern-matching versions which
result in a mixture of right- and left-currying.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607

From: Hrvoje Blazevic
Subject: Re: combination of applications
Date: 
Message-ID: <calcv8$vnv$1@ls219.htnet.hr>
Rob Warnock wrote:
> Stefan Ram <···@zedat.fu-berlin.de> wrote:
> +---------------
> |   Are there means in Lisp with the same effect, possibly
> |   something like the following?
> | ( combine f g h x )
> +---------------
> 
> Do a Web search for the terms COMPOSE and/or CURRY. Note that if
> any of the functions but the last one take more than one argument,
> you will need to CURRY that function with N-1 arguments before
> COMPOSE'ing it.
> 

This is a rather terse information. An easy example should probably help:

We can consider CPS to be a composition of functions (where the 
continuation is built as a composition of the rest of the computation 
(k), and the actual calculation to be carried out on each call. A simple 
example would be the fib function:

(defun fib (n k)
   (if (< n 2)
       (funcall k n)
     (fib (1- n)
	 (compose k (lambda (a)
		      (fib (- n 2)
			   (lambda (b) (+ a b))))))))

CL-USER> (fib 8 (lambda (x) x))
21

;; where compose is defined as in jrm's post

This is sort of ad-hoc implicit currying of +.


Of course this would be more elegant if explicit curry is applied as in:

(defun curry (f &optional (arity 2))
   (labels ((c (a k)
	      (if (= a 0)
		  (funcall k '())
		(lambda (&rest args)
		  (c (- a (length args))
		     (compose k (lambda (acc-args)
				  (append args acc-args))))))))
     (c arity (lambda (args) (apply f args)))))


(defun fib (n k)
   (if (< n 2)
       (funcall k n)
       (fib (- n 1)
	   (compose k
		    (funcall (curry #'fib) (- n 2))
		    (curry #'+)))))


(fib 8 (lambda (x) x))
21


I'm aware that this is (probably) a very clumsy Cl code. The reason 
should be obvious.  I wrote this as an exercise in Scheme -- Scheme 
being (IMHO) more elegant when it comes to this type of programming. The 
original code for fib is:

(define (fib n k)
   (if (< n 2)
       (k n)
       (fib (- n 1)
	   (compose k ((curry fib) (- n 2)) (curry +)))))


-- Hrvoje
From: Rob Warnock
Subject: Re: combination of applications
Date: 
Message-ID: <k5Cdnajr0J89DlLdRVn-jg@speakeasy.net>
Hrvoje Blazevic  <······@despammed.com> wrote:
+---------------
| > Do a Web search for the terms COMPOSE and/or CURRY. Note that if
| > any of the functions but the last one take more than one argument,
| > you will need to CURRY that function with N-1 arguments before
| > COMPOSE'ing it.
| 
| This is a rather terse information. An easy example should probably help:
+---------------

Except that your example is rather complex. In introductory texts,
the usual definition of CURRY does simple partial application, e.g.:

    > (defun curry (f &rest curried-args)	; sometimes called CURRY-LEFT
	(lambda (&rest args)
	  (apply f (append curried-args args))))
    > (funcall (curry (curry (curry #'+ 17) 12) 51) -42)

    38
    > (funcall (curry #'+ 17 12) 51 -42)	; or more than one at a time

    38
    > 

AFAICT, your CURRY only works for functions of fixed arity, which is
certainly useful in many cases, but can be restrictive at times.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Hrvoje Blazevic
Subject: Re: combination of applications
Date: 
Message-ID: <cap5t5$6h3$1@ls219.htnet.hr>
Rob Warnock wrote:
> Hrvoje Blazevic  <······@despammed.com> wrote:
> +---------------
> | > Do a Web search for the terms COMPOSE and/or CURRY. Note that if
> | > any of the functions but the last one take more than one argument,
> | > you will need to CURRY that function with N-1 arguments before
> | > COMPOSE'ing it.
> | 
> | This is a rather terse information. An easy example should probably help:
> +---------------
> 
> Except that your example is rather complex. In introductory texts,
> the usual definition of CURRY does simple partial application, e.g.:
> 
>     > (defun curry (f &rest curried-args)	; sometimes called CURRY-LEFT
> 	(lambda (&rest args)
> 	  (apply f (append curried-args args))))
>     > (funcall (curry (curry (curry #'+ 17) 12) 51) -42)
> 
>     38
>     > (funcall (curry #'+ 17 12) 51 -42)	; or more than one at a time
> 
>     38
>     > 
> 
> AFAICT, your CURRY only works for functions of fixed arity, which is
> certainly useful in many cases, but can be restrictive at times.
> 

True, but the reason for my posting was not to present general CURRY. 
Written this way (with fixed arity) it is designed to work inside 
compose, inside continuation building. Actually, for this to work (where 
  -- unlike in fib, k takes more than one argument) the COMPOSE I used 
(jrm's) is not enough. This was designed for something I called 
compose-with-curry, where there are arguments that the current function 
should not grab, but leave to the next one in line.

The real reason for my post was that I found an interesting parallelism 
with the way this thread was going, to my own train of thought after 
having read one sentence in C. Queinnec's LiSP (section 3.6): "Since the 
receiver will be applied to 1 in the end (talking about factorial), 
there's nothing left to do but compose the receiver and the 
supplementary handling and thus get ..."

The word he used "compose", made me think about continuations in a new 
light, so if CPS is really a composition of functions, then we should be 
able to explicitly use COMPOSE. The next step was to combine it with 
CURRY ... and then -- problems hit :-)

BTW: your CURRY (for the reasons stated earlier) does not work with my 
examples.

-- Hrvoje