Page 1 of 1

In-place parameter substitution

Posted: Thu Apr 12, 2012 4:10 pm
by genghis
Hi, is it possible to create a user-defined function much like what inc does: in-place parameter substitution, or is this only available for built-in functions?

Where do newLISPers hangout? Is there a #newlisp IRC channel somewhere?

Re: In-place parameter substitution

Posted: Thu Apr 12, 2012 4:45 pm
by Lutz
There is a chapter about this on this page:

http://www.newlisp.org/index.cgi?Closures

look for "Stateful functions using in-place modification: at the end.

Re: In-place parameter substitution

Posted: Thu Apr 12, 2012 5:08 pm
by genghis
Let me clarify my question:

Is it possible to create my version of inc, my-inc?

Code: Select all

(define (sum (x 0)) (my-inc 0 x))
(sum 1) ;=> 1
(sum 2) ;=> 3
sum ;=> (lambda ((x 0)) (my-inc 3 x))
My gut instinct tells me in order to have a self-modifying code like the above, my-inc must have a reference to the enclosing lambda list. How do I go about creating my-inc ? Is this possible?

Re: In-place parameter substitution

Posted: Sat Apr 14, 2012 12:43 am
by Kazimir Majorinc
How about this one for beginning:

(define-macro (myinc p0)(set p0 (+ (eval p0) 1)))

Re: In-place parameter substitution

Posted: Sat Apr 14, 2012 6:49 am
by genghis
Kazimir Majorinc wrote:How about this one for beginning:

(define-macro (my-inc p0)(set p0 (+ (eval p0) 1)))
The above fails with the following error when called through my sum function above:
ERR: symbol expected in function set : p0

What I'm interested is having a function/macro/fexpr that can modify its arguments in-place, exactly like what inc does: i.e., it works even with literal numbers. Is this possible or do built-ins like inc and dec can only be implemented by the underlaying newLISP C implementation?

Re: In-place parameter substitution

Posted: Sat Apr 14, 2012 2:29 pm
by Lutz
Any destructive primitive could be used to do this, when there is a way to reference the currently executing lambda expression:

Code: Select all

> (define (selfmod x) (setf (last selfmod) (+ (last selfmod) 1)) 0)
(lambda (x) (setf (last selfmod) (+ (last selfmod) 1)) 0)
> (selfmod)
1
> (selfmod)
2
> (selfmod)
3
> selfmod
(lambda (x) (setf (last selfmod) (+ (last selfmod) 1)) 3)
A user-defined function has no way to reference the function it was invoked from, except when it has previous knowledge of it:

Code: Select all

> (define (selfinc x) (myinc x) 0)
(lambda (x) (myinc x) 0)
> (define (myinc x) (inc (last selfinc) x))
(lambda (x) (inc (last selfinc) x))
> (selfinc 1)
1
> (selfinc 2)
3
> (selfinc 3)
6
> selfinc
(lambda (x) (myinc x) 6)
> 

Re: In-place parameter substitution

Posted: Sat Apr 14, 2012 3:19 pm
by Kazimir Majorinc
It would be nice to have some function that returns list of the caller functions, similarly like (sys-info 3) returns the level of recursion. Although it sounds quite 'dangerous' it can actually provide some debugging facilities, i.e. functions could react if called by someone they do not appreciate.

Re: In-place parameter substitution

Posted: Sun Apr 15, 2012 8:21 am
by tumble
Kazimir Majorinc wrote:It would be nice to have some function that returns list of the caller functions, similarly like (sys-info 3) returns the level of recursion. Although it sounds quite 'dangerous' it can actually provide some debugging facilities, i.e. functions could react if called by someone they do not appreciate.
The Io language has this. I think it's built it at rather a low level, though.

Re: In-place parameter substitution

Posted: Sun Apr 15, 2012 2:43 pm
by Lutz

Code: Select all

(define (callers) 
    (catch (0) 'error) 
    (slice (map sym (find-all "function (\\w+)" error $1 0)) 3) 
)

(define (foo) (bar))
(define (bar) (baz))
(define (baz) (callers))

(foo) => (baz bar foo)
Instead of 3 in the last statement of 'callers' put 4 to exclude the current function.

I had this function coded natively a while back for experimentation, but couldn't really find any good use for it. Similar to 'estack', which was even shipped - undocumented - for a for a few versions and returned the variable environment stack. These functions seem interesting too me too, but I cannot see useful applications, it is just overhead nobody ever uses. When you really have a situation, where a function needs to know the caller, just make it a parameter of the function call.

Above code is not the only way to implement this. A while back Cormullion showed how you could redefine 'define' to include debugging code. In the current case, it would mean pushing the function symbol on a 'callers' stack as first statement of each function.