In-place parameter substitution

Started by genghis, April 12, 2012, 09:10:52 AM

Previous topic - Next topic

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?

Lutz

#1
There is a chapter about this on this page:



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



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

genghis

#2
Let me clarify my question:



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



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

Kazimir Majorinc

#3
How about this one for beginning:



(define-macro (myinc p0)(set p0 (+ (eval p0) 1)))
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

genghis

#4
Quote from: "Kazimir Majorinc"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?

Lutz

#5
Any destructive primitive could be used to do this, when there is a way to reference the currently executing lambda expression:


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


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

Kazimir Majorinc

#6
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.
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

tumble

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


The Io language has this.  I think it's built it at rather a low level, though.

Lutz

#8
(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.