How does (define (sum (x 0)) (inc 0 x)) work?

Q&A's, tips, howto's
Locked
gatesphere
Posts: 7
Joined: Wed Nov 07, 2012 4:22 pm

How does (define (sum (x 0)) (inc 0 x)) work?

Post by gatesphere »

Hello all...

So I came across this example function in the Code Patterns guide. I'm new to newlisp, so this code is confusing me. How does this function have memory?

Code: Select all

(define (sum (x 0)) (inc 0 x))
I understand that (x 0) means that 0 is a default value for x, what I'm not understanding is why does sum rewrite itself?

I've traced it, and found that after a (sum 4), sum => (lambda ((x 0)) (inc 4 x))... this confuses me.

Any help? Thanks.

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by cormullion »

Here's an easier example to get you started:

Code: Select all

> (define (changeme x) (setf (last changeme) (+ (last changeme) 1)) 0)
> (changeme)
1
> (changeme)
2
> (changeme)
3
> changeme
(lambda (x) (setf (last changeme) (+ (last changeme) 1)) 3)
> 
The explicit setf shows how you can modify the function's definition. How the sum example works is harder to explain.

For more fun, consider Kazimir's tractor, or many other of his delightful newLISP toys.

gatesphere
Posts: 7
Joined: Wed Nov 07, 2012 4:22 pm

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by gatesphere »

Thanks cormullion.

I had found Kazimir's example prior to the (sum) example. I understand Kazimir's function.

I'm having a hard time understanding either (sum) or the (changeme) that you introduced...

Is there any way you could walk me through what happens?

Thanks.

EDIT: Okay, I understand (changeme) now. It modifies the last element of the lambda by adding one to it each time it's called. That's nice.

But how does (sum) do it's magic? It doesn't look like there's anything to change... 0 is a number...

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by cormullion »

newLISP manual wrote:(inc place [num])
inc increments a/the number in place, so works with both symbols and numbers. So you can do (inc 0) easily enough. But for the precise evaluation process inside an evaluating function, I'm not sure how that works, although you could read this to see if it helps.

jopython
Posts: 123
Joined: Tue Sep 14, 2010 3:08 pm

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by jopython »

cormullion,

In other Lisp's this function is called a closure.
But newlisp does not support closures. If then what is it?

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by cormullion »

No idea - I know little about these CS topics. I've seen "homoiconicity" mentioned. Or was it the "code is data" paradigm? "First-class functions"? "Metaprogramming"? Perhaps someone with some knowledge will be along presently...

denis
Posts: 20
Joined: Wed Apr 27, 2011 12:19 pm
Location: Petsamo, Murmansk, RU

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by denis »

the same effect happens with this function:

Code: Select all

> (define (pp x) (push x '()))
(lambda (x) (push x '()))
> (pp 1)
(1)
> pp
(lambda (x) (push x '(1)))
> (pp 3)
(3 1)
> pp
(lambda (x) (push x '(3 1)))
For some reason the function creates a closure for its literals? (sounds sane? :-) )

saulgoode
Posts: 10
Joined: Sat Jul 16, 2011 6:15 am

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by saulgoode »

gatesphere wrote:I've traced it, and found that after a (sum 4), sum => (lambda ((x 0)) (inc 4 x))... this confuses me.
Consider the syntax diagram for how the expression "(inc 0 x)" might be stored in memory.

Image

The 'inc' primitive, when invoked with its first argument being a literal number, apparently behaves by updating the memory cell of that atomic number (represented in the diagram by the oval containing a blue "0"). If the expression, "(inc 0 x)" is evaluated by itself on the command line, the "0" cell is updated but then destroyed when the function is completed (in Scheme the cell would be released for later garbage collecting, but my understanding is that Newlisp does not produce such garbage).

However, since in your example "(inc 0 x)" is contained within the lambda definition of 'sum', the "0" cell (indeed the entire lambda expression) persists in memory. So when you execute "(sum 4)", the "0" cell is updated to contain "4", which continues to persist within the definition of 'sum'.

That would be my characterization of what is occurring -- the "magic" of the function modifying itself takes place inherently within the execution of 'inc', not through any explicit manipulation of the AST of 'sum'. I could, of course, be completely off-base (the documentation for 'inc' does not seem to cover in detail the case of the 'place' parameter being a literal number).

gatesphere
Posts: 7
Joined: Wed Nov 07, 2012 4:22 pm

Re: How does (define (sum (x 0)) (inc 0 x)) work?

Post by gatesphere »

Thanks so much for this! It makes a lot of sense. And it seems to be correct, based on the following experiment:

Code: Select all

newLISP v.10.4.4 on Linux IPv4/6 UTF-8, execute 'newlisp -h' for more info.

> (setf a '(inc 0 1))
(inc 0 1)
> a
(inc 0 1)
> (eval a)
1
> a
(inc 1 1)
> (eval a)
2
> a
(inc 2 1)

Locked