Is there the name conflict of lambda in newlisp?

Q&A's, tips, howto's
Locked
iNPRwANG
Posts: 32
Joined: Sun May 08, 2011 1:45 pm

Is there the name conflict of lambda in newlisp?

Post by iNPRwANG »

I'm sorry for my english. While I run under codes, I can not understand why the result is 10 unless the myfun's lambda parameter use the variable "a" defined of myfun2. And the common lisp get the right results :30.


Code: Select all

(define (myfun2 fun)
	(let ((a 20))
		(apply fun '())
		)
	)

(define (myfun)
	(let ((a 10))		
		(myfun2 
			(lambda () 
				(setq a 30))
			)
		a
		)
	)
       
(print (myfun))

(exit)

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

Re: Is there the name conflict of lambda in newlisp?

Post by Kazimir Majorinc »

Newlisp uses dynamic scope. That means that application of (lambda()(setq a 30)) doesn't refer to binding of a on the place of definition of (lambda()(setq a 30)), in this case in myfun, but on binding of a in the place of application, i.e. in myfun2.

It is how it was in original, McCarthy's Lisp. Then Scheme introduced lexical scoping and Common Lisp followed (although CL supports dynamic scope if you declare local variables as special). It is one of the most controversial issues in Lisp.

iNPRwANG
Posts: 32
Joined: Sun May 08, 2011 1:45 pm

Re: Is there the name conflict of lambda in newlisp?

Post by iNPRwANG »

Thanks a lot!
I'v read the common lisp special, and I'v understand the newlisp uses the dynamic scope, the common lisp could use (declare (special xxx)) to let a variable's scope be dynamic.

But, had newlisp got a solution to avoid the name conflict of dynamic scope? Such as, I often use the variable name of "tmp", and how to avoid the name confilct of another function.

I'm thinking a way about could a function to construct a function-local-context to store the function local variable, and auto destroy while the function end. (by modify the newlisp's design : P )The code like this:

Code: Select all

(define (myfun2 fun)
   (let ((a 20))
      (apply fun '())
      )
   )

(define (myfun)	
   (let ((myfun:a 10))	  
      (myfun2		
         (lambda ()			
            (setq myfun:a 30))
         )
      myfun:a
      )
   )
       
(print (myfun))
(exit)



conan
Posts: 52
Joined: Sat Oct 22, 2011 12:14 pm

Re: Is there the name conflict of lambda in newlisp?

Post by conan »

I'm not sure I fully understand what you're trying to achieve. However I can tell you that you avoid name conflicts by using contexts.

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

Re: Is there the name conflict of lambda in newlisp?

Post by Kazimir Majorinc »

The conflict might happen only if you pass "free variable" around; that is the case with

Code: Select all

(lambda()(setf a 3))
but not with

Code: Select all

(lambda()(let((a 4))(setf a 3))).
As long as one does not pass free variables around he is safe. The problem most frequently occurs with Newlisp macros (actually, fexprs). These rely on free variables. If one defines ifnt, inverse of if with

Code: Select all

 (define-macro (ifnt condition else then)
     (if (eval condition) 
         (eval then) 
         (eval else)))
then all variables used in, for example,

Code: Select all

(ifnt (< a b) (setf a 4)(setf b 4))
are passed to ifnt as free variables. In that case the problem is exactly the same as in Common Lisp macros, where the solution is in use of gensyms. Newlisp doesn't have gensym, but one can easily define his own.

Code: Select all

(define (gensym)
   (inc gensym-counter)
   (sym (append "G-" (string gensym-counter))))
However, in almost all cases, use of gensym is overkill. I defined two functions for myself: set-protected1 and set-protected2.

Code: Select all

(set-protected1 'ifnt (lambda(c e t)(if (eval c)(eval t)(eval e))) 
                      '(e c t))
will actually produce code lambda-expression like

Code: Select all

(lambda([ifnt.c] [ifnt.e] [ifnt.t])
    (if (eval [ifnt.c])
        (eval [ifnt.t])
        (eval [ifnt.e])))
Which is "safe" because it uses unique names. Good news is that you do not need to use my set-protected1 or to write your own - as conan wrote, Newlisp provides "contexts" which do that for yourself. Look on this REPL communication.

Code: Select all

> (context 'ifnt)
ifnt
ifnt> (define-macro (ifnt:ifnt c e t)(if (eval c) (eval t) (eval e)))
(lambda-macro (c e t)
 (if (eval c)
  (eval t)
  (eval e)))
ifnt> (context 'MAIN)
MAIN
> (ifnt (< 2 3) ">=" "<")
"<"
> ifnt:ifnt
(lambda-macro (ifnt:c ifnt:e ifnt:t)
 (if (eval ifnt:c)
  (eval ifnt:t)
  (eval ifnt:e)))
>
It is probably exactly what you need. It is also recommended approach by designer of the language.

Neither set-protected1 nor contexts are "safe" in one very special case - if recursive macro passes one of its variables as free variable from one instance of the macro to another instance of the same macro, where it will be accessed inside new binding of the same variable. It is so rare case that I never encountered something like that, and as it was discussed on this forum, it turned that noone reported that he experienced that problem.

If problem is still interesting from theoretical point of view, you can look at my blogpost

http://kazimirmajorinc.blogspot.com/200 ... exprs.html

It contains implementation of set-protected1 and set-protected2, last does exactly what you proposed "function to construct a function-local-context to store the function local variable, and auto destroy while the function end", which turns to be relatively complicated from technical point of view. I must warn it is not how typical "production code" looks like, it is how it looks if one wants to play with Lisp.

iNPRwANG
Posts: 32
Joined: Sun May 08, 2011 1:45 pm

Re: Is there the name conflict of lambda in newlisp?

Post by iNPRwANG »

Thanks, this solution of define function as context default functor can avoid name conflict in most case. : )

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

Re: Is there the name conflict of lambda in newlisp?

Post by Lutz »

Here is a function you can use to define functions as default functors in their own space:

Code: Select all

(define (def-static s body) 
      (def-new 'body (sym s s))) 
and use like this:

Code: Select all

> (def-static 'acc (fn (x) (inc sum x)))
acc:acc
> (acc 1)
1
> (acc 1)
2
> (acc 1)
3
> (acc 5)
8
> acc:acc
(lambda (acc:x) (inc acc:sum acc:x))
> 
fn is the same as lambda but quicker to write.

iNPRwANG
Posts: 32
Joined: Sun May 08, 2011 1:45 pm

Re: Is there the name conflict of lambda in newlisp?

Post by iNPRwANG »

Lutz wrote:Here is a function you can use to define functions as default functors in their own space:

Code: Select all

(define (def-static s body) 
      (def-new 'body (sym s s))) 
and use like this:

Code: Select all

> (def-static 'acc (fn (x) (inc sum x)))
acc:acc
> (acc 1)
1
> (acc 1)
2
> (acc 1)
3
> (acc 5)
8
> acc:acc
(lambda (acc:x) (inc acc:sum acc:x))
> 
fn is the same as lambda but quicker to write.
Thank you for the nice solution!

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

Re: Is there the name conflict of lambda in newlisp?

Post by tumble »

Thanks, Lutz. I really like the syntax of that definition (def-static).

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

Re: Is there the name conflict of lambda in newlisp?

Post by jopython »

Lutz,

Is it possible to use the def-static with lambda-macro?

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

Re: Is there the name conflict of lambda in newlisp?

Post by Lutz »

You can do this:

Code: Select all

> (def-static 'mysetq (lambda-macro (p1 p2) (set p1 (eval p2))))
mysetq:mysetq
> (mysetq x 123)
123
and this is what got generated:

Code: Select all

> mysetq:mysetq
(lambda-macro (mysetq:p1 mysetq:p2) (set mysetq:p1 (eval mysetq:p2)))
> 
There is also another definition of 'def-static' which can be used like 'define', but is not suitable for macros:

http://www.newlisp.org/code/def-static.html

also linked from here:

http://www.newlisp.org/index.cgi?page=D ... ther_LISPs

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

Re: Is there the name conflict of lambda in newlisp?

Post by jopython »

Thank you.
Maybe "def-static" should become a newlisp 'builtin'

Locked