Closure?

Pondering the philosophy behind the language

Closure?

Hi!

I'm working through the early examples of the "Stratified Design" paper and I've run (almost immediately!) into something that doesn't seem to work.

They describe an average-damp function that given a function, returns a new function that averages the value with the result of the function:

Code: Select all
(define (average)
(div (apply 'add (args)) (length (args))))

(define (average-damp f)
(fn (x)
(average x (f x))))

You might use it like this: ((average-damp (fn (y) (+ 2 y))) 3)

And expect to get 4 (the average of 3 and the result of adding 2 to 3). However, instead I get this:

Code: Select all
ERR: invalid function : (f x)
called from user defined function average

I assume that this is happening because the function f, that is passed to average-damp is not lexically closed in the new function that's returned, because NewLisp is not doing that sort of thing.

I have looked through the "Functions as Data" section of the Code Patterns and those examples didn't seem to help. I tried both "expand" and "letex" and they didn't seem to help.

So, is it possible to implement something like average-damp in NewLisp, and how would you do it?

Thanks!

 See http://dspace.mit.edu/bitstream/handle/ ... sequence=2
Testing can show the presence of bugs, but not their absence.
oofoe

Posts: 60
Joined: Wed Sep 28, 2005 7:13 pm

Re: Closure?

You are correct that the reliance on lexical scope is causing the problem. In the manual, Lutz talks about what you should do in this case. From http://www.newlisp.org/downloads/newlis ... html#letex.

In the second example a function make-adder is defined for making adder functions:

Code: Select all
(letex (c n) (lambda (x) (+ x c))))

(define add3 (make-adder 3)) → (lambda (x) (+ x 3))

(add3 10) → 13

letex evaluates n to the constant 3 and replaces c with it in the lambda expression.

So your definition of average-damp in this case might be:

Code: Select all
> (define (average-damp f)
(letex ([f] f)
(fn (x) (average x ([f] x)))))

> ((average-damp (fn (y) (+ 2 y))) 3)
4

Hope that helps.
(λx. x x) (λx. x x)
rickyboy

Posts: 595
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Re: Closure?

Code: Select all
(define (average)
(div (apply add (args)) (length (args))))

(define (average-damp f)
(apply average (append (map f (args)) (args))))

I assume a dampening factor has to be applied to every argument, as in the second example

Code: Select all
> (average-damp (fn (x) (+ 2 x)) 3)
4
> (average-damp (fn (x) (+ 2 x)) 3 4 5 6)
5.5
>

Note, that the x is not a free variable in (fn (x)...) and is protected so the following won't harm:

Code: Select all
> (set 'x 3)
3
> (average-damp (fn (x) (+ 2 x)) x (+ x 1) (+ x 2) (+ x 3))
5.5
>

also: fn is just a shorter writing for lambda

:-) I just see, rickyboy and I posted at the same time, but two different solutions

the function passed doesn't need to be anonymous:

Code: Select all
> (define (my-damp x) (+ 2 x))
(lambda (x) (+ 2 x))
> (average-damp my-damp 3)
4
> (average-damp my-damp 3 4 5 6)
5.5
>
Lutz

Posts: 5279
Joined: Thu Sep 26, 2002 4:45 pm

Re: Closure?

Very nice, Lutz!
(λx. x x) (λx. x x)
rickyboy

Posts: 595
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia 