Closure?

Pondering the philosophy behind the language

Closure?

Postby oofoe » Thu Apr 04, 2013 12:03 pm

Hi!

I'm working through the early examples of the "Stratified Design" paper[1] 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!

[1] 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?

Postby rickyboy » Thu Apr 04, 2013 1:49 pm

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
(define (make-adder n)
    (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: 582
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Re: Closure?

Postby Lutz » Thu Apr 04, 2013 2:12 pm

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: 5276
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California

Re: Closure?

Postby rickyboy » Thu Apr 04, 2013 2:32 pm

Very nice, Lutz!
(λx. x x) (λx. x x)
rickyboy
 
Posts: 582
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia


Return to Whither newLISP?

Who is online

Users browsing this forum: No registered users and 1 guest