In-place parameter substitution

Pondering the philosophy behind the language
Locked
genghis
Posts: 4
Joined: Thu Apr 12, 2012 3:55 pm

In-place parameter substitution

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

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: In-place parameter substitution

Post 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.

genghis
Posts: 4
Joined: Thu Apr 12, 2012 3:55 pm

Re: In-place parameter substitution

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

Kazimir Majorinc
Posts: 388
Joined: Thu May 08, 2008 1:24 am
Location: Croatia
Contact:

Re: In-place parameter substitution

Post by Kazimir Majorinc »

How about this one for beginning:

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

genghis
Posts: 4
Joined: Thu Apr 12, 2012 3:55 pm

Re: In-place parameter substitution

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

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: In-place parameter substitution

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

Kazimir Majorinc
Posts: 388
Joined: Thu May 08, 2008 1:24 am
Location: Croatia
Contact:

Re: In-place parameter substitution

Post 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.

tumble
Posts: 8
Joined: Wed Dec 28, 2011 4:17 pm
Contact:

Re: In-place parameter substitution

Post 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.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: In-place parameter substitution

Post 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.

Locked