Subject: Re: Primitive or Confusing?
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 21 Oct 2000 04:00:50 GMT
Newsgroups: comp.lang.scheme
Message-ID: <8sr4di$1o6n$1@fido.engr.sgi.com>
dognews <frankque@infinet.net> wrote:
+---------------
| I'm so confused by such a kind of piece:
| (define A
|    (lambda (x)
|      (lambda (y)
|        (body))))
| When A is called with one argument which will pass to the first lambda for
| x; then you have to call another procedure, namely a outside name to pass
| another argument for y in the nested lambda.
+---------------

Not an outside "name", just another call. E.g., ((A 37) 43)
will evaluate "body" with "x" bound to 37 and "y" bound to 43,
as will (let ((foo (A 37))) (foo 43)).

+---------------
| It seems to hide y inside of A...
+---------------

Actually, what it "hides" is "x", inside the closure that "A" returns.
A value for "y" must be supplied when you *call* the procedure that
"A" returns.

+---------------
| and that makes hard understanding of whole process of evaluation.
+---------------

I understand that closures may be initially hard to understand,
especially if you're only used to languages which don't allow
procedures to be created (or even defined!) inside other procedures,
but I assure you the benefits of understanding them are well
worth the trouble. Such closures [can] capture the very essence
of "object-oriented programming".

+---------------
| What is its practical significance or reason to employ?
+---------------

Let's try your above definition in a concrete example with more verbose
and descriptive names, and see if it doesn't suggest some applications:

	> (define make-procedure/add-a-constant
	    (lambda (the-constant-to-add)
	      (lambda (the-variable-arg)
		(+ the-variable-arg the-constant-to-add))))

or even more verbosely:

	> (define make-procedure/add-a-constant
	    (lambda (the-constant-to-add)
	      (let ((the-new-procedure
		      (lambda (the-variable-arg)
			(+ the-variable-arg the-constant-to-add))))
		the-new-procedure)))

Having done that, we can now do:

	> (define add-5 (make-procedure/add-a-constant 5))  
	> (define add-27 (make-procedure/add-a-constant 27))
	> add-5
	#<procedure>
	> (add-5 4)
	9
	> (add-27 4)
	31
	> (add-5 17)
	22
	> (add-27 17)
	44
	> 

Does that give you any ideas for other applications? For example, how
would you define a procedure "make-procedure/multiply-by-a-constant"?

Going even further, how might you generalize from those two examples
to define a procedure "make-procedure-with-some-but-not-args-supplied",
or "curry" [the name more commonly used in the literature, after a
gentleman named Haskell Curry (for whom the language "Haskell" is
also named).] Such a "curry" procedure could be used to define the
"add-5" procedure above as follows:

	> (define add-5 (curry + 5))
	> (add-5 4)
	9
	>

but could also be used on other functions, e.g.:

	> (define mul-6 (curry * 6))
	> (mul-6 3)
	18
	> (define f-b-list (curry list 'foo 'bar))
	> (f-b-list 12 'sam 25)
	(foo bar 12 sam 25)
	> 

[In practice, you may find it useful to distinquish between "curry-left"
and "curry-right", but that's another story...]

+---------------
| Another related question is how to define a procedure that returns a
| procedure that applies the first procedure to a string but the procedure
| requires char as its argument.
+---------------

I'm at a loss to figure out the antecedent of "the first procedure".
Did you mean "the ARGUMENT of the first procedure"? Or if not, could
you restate the question more clearly?  [...if & only if it's *not*
a homework assignment, that is.]

In any case, it sounds like you're trying to achieve something close to:

	(curry (lambda (p s) (map p (string->list s))) SOME-PROC)


-Rob

-----
Rob Warnock, 31-2-510		rpw3@sgi.com
Network Engineering		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043