Subject: Re: Functional programming
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 1999/11/11
Newsgroups: comp.lang.lisp
Message-ID: <80eaq1$64l28@fido.engr.sgi.com>
Antonio Leitao  <aml@gia.ist.utl.pt> wrote:
+---------------
| >>>>> "Rob" =3D=3D Rob Warnock <rpw3@rigden.engr.sgi.com> writes:
|  Rob> Scheme-the-standard doesn't give you a *choice* other than
|  Rob> (presumably slow) "eval", so passing closures is usually
|  Rob> considered the "only right thing".
| 
| I don't understand why must we use eval.
+---------------

Because the original problem being discussed was hooks that are lists
of *symbols*, as is often done in Emacs & CL, not closures. That is:

	(define my-hooks (list 'func1 'func2))

Now, if (for better or worse) that's how the hook is *defined*, how
do you call those functions in *standard* Scheme without using "eval"?
[...or a non-standard extension such as MzScheme's "global-defined-value".]

+---------------
| What's the problem with this approach?
...
| (define my-hooks (list func1 func2))
...
| (define (run-hooks hooks)
|   (for-each (lambda (hook) ((car hook))) hooks))
+---------------

[Uh... You don't need the "car"; "for-each" does that for you.]

Well, your hook variable is a list of *closures*, not symbols.
That certainly "works" (for some definitions of "work"), but fails
to address two of the issues others expressed in this thread:
(1) that the traditional Lisp hook style is to use symbols, and
(2) that using symbols instead of closures has the advantage of
automatically using the *new* value of any hook function that's
redefined, even *after* being added to the hook. Compare both ways:

	> (define (foo) (print "foo"))
	> (define (bar) (print "bar"))
	> (define sym-hook (list 'foo 'bar))	; the symbol-based version
	> (define (do-sym-hooks)
	    (for-each (lambda (x) ((eval x))) sym-hook))
	> (define clo-hook (list foo bar))	; the closure-based version
	> (define (do-clo-hooks)
	    (for-each (lambda (x) (x)) clo-hook))
	> (do-sym-hooks)
	foo
	bar
	> (do-clo-hooks)
	foo
	bar
	>

The same so far, yes? Now look what happens when we redefine one
of the hook functions:

	> (define (foo) (print "this is a new, improved foo!!"))
	> (do-sym-hooks)
	this is a new, improved foo!!
	bar
	> (do-clo-hooks)
	foo
	bar
	>

Oops!!


-Rob

p.s. Yes, there are ways to get around this problem *without* using
"eval", e.g., make every hook function be a trampoline for the "real"
function, the one that gets edited:

	> (define (real-foo) (print "foo"))
	> (define (foo) (real-foo))
	> (define clo-hook (list foo bar))
	> (do-clo-hooks)
	foo
	bar
	> (define (real-foo) (print "this is a new, improved foo!!"))
	> (do-clo-hooks)
	this is a new, improved foo!!
	bar
	>

But 'tis a bit cumbersome, yes?

-----
Rob Warnock, 8L-846		rpw3@sgi.com
Applied Networking		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		FAX: 650-933-0511
Mountain View, CA  94043	PP-ASEL-IA