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

Started by gatesphere, November 07, 2012, 08:26:06 AM

Previous topic - Next topic

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?


(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

#1
Here's an easier example to get you started:


> (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  http://kazimirmajorinc.blogspot.co.uk/2009/04/crawler-tractor.html">Kazimir's tractor, or many other of his delightful newLISP toys.

gatesphere

#2
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

#3
Quote from: "newLISP manual"(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 http://www.newlisp.org/ExpressionEvaluation.html">this to see if it helps.

jopython

#4
cormullion,



In other Lisp's this function is called a closure.

But  newlisp does not support closures. If then what is it?

cormullion

#5
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

#6
the same effect happens with this function:



> (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

#7
Quote from: "gatesphere"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.



http://www.kerosenecow.net/data/images/misc/inc-ast.png">



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

gatesphere

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



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)