Is there an equivalent to flet or labels?

Started by gatesphere, December 06, 2012, 09:12:34 AM

Previous topic - Next topic

gatesphere

Hi all,



Wondering if there's an equivalent to flet or labels in newLISP.  I don't see any in the docs.  There might be a way to hack it together with letex and lambda, but I'm not sure.



Any help?



Thanks.

johu

#1
For example:



(context 'MAIN:labels)
(define-macro (labels:labels)
  (letex (_labels (append '(let)
                           (list (map (fn (x) (list (x 0) (append '(fn) (list (x 1)) (2 x)))) (args 0)))
                           (1 (args))))
     _labels))
(context MAIN)

Then:


D:>newlisp -n
newLISP v.10.4.5 on Win32 IPv4/6 libffi, execute 'newlisp -h' for more info.

> labels
nil
> [cmd]
(context 'MAIN:labels)
(define-macro (labels:labels)
  (letex (_labels (append '(let)
                           (list (map (fn (x) (list (x 0) (append '(fn) (list (x
 1)) (2 x)))) (args 0)))
                           (1 (args))))
     _labels))
(context MAIN)
(define (test-a x)
        (labels ((in-test (x y) (println "test-a " x " " y)))
          (in-test x "a")))

(define (test-b x)
        (labels ((in-test (x y) (println "test-b " x " " y)))
          (in-test "b" x)))

(define (in-test x)
        (println "test-out " x))
[/cmd]
labels
(lambda-macro ()
 (letex (_labels (append '(let) (list (map (lambda (x) (list (x 0) (append '(lam
bda )
         (list (x 1))
         (2 x))))
      (args 0)))
    (1 (args)))) _labels))
MAIN
(lambda (x) (labels ((in-test (x y) (println "test-a " x " " y))) (in-test x "a"
)))
(lambda (x) (labels ((in-test (x y) (println "test-b " x " " y))) (in-test "b" x
)))
(lambda (x) (println "test-out " x))
> (in-test "in-test")
test-out in-test
"in-test"
> (test-a "test-a")
test-a test-a a
"a"
> (test-b "test-b")
test-b b test-b
"test-b"
> (in-test "in-test")
test-out in-test
"in-test"
> [cmd]
(define (test-2 x y)
        (labels ((test-x (x) (println "test1 x=" x))
           (test-y (x) (println "test2 y=" x)))
          (test-x x)
          (test-y y)))
[/cmd]
(lambda (x y) (labels ((test-x (x) (println "test1 x=" x)) (test-y (x) (println
"test2 y="
     x)))
  (test-x x)
  (test-y y)))
> (test-2 "a" "b")
test1 x=a
test2 y=b
"b"
>

gatesphere

#2
That's some nice code.



However, I'm failing when trying to use it to write another macro based on it:


(define-macro (alambda)
  (labels ((self (args 0) (1 args)))
    self))

(setf 'a (alambda (n) (if (= n 0) 1 (* n (self (- n 1))))))

(println (a 5))


I'm getting these errors:


ERR: symbol is protected in function let : self
called from user defined function labels
called from user defined function alambda


I'd like to be able to access "self" from a macro definition, so that I can define an anaphoric lambda macro to provide easy recursion.



:( My search continues.

Lutz

#3
newLISP is not Common Lisp or Scheme and any intent to program in it, like you would in Common Lisp or Scheme, will end in frustration ;)



Try to solve your application problems with the functions built in to newLISP first. Not until you know newLISP's API well, write your own helpers to extend the language.



If you want to enjoy newLISP solving real world application problems, you have to program with newLISP on its own terms. A good start is to read the documentation and introductions available online:



The standard online documentation:



http://www.newlisp.org/downloads/newlisp_manual.html">http://www.newlisp.org/downloads/newlisp_manual.html



http://www.newlisp.org/downloads/CodePatterns.html">http://www.newlisp.org/downloads/CodePatterns.html



Some explanation about differences between newLISP and other Lisps:



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



An introduction for beginners:



http://en.wikibooks.org/wiki/Introduction_to_newLISP">http://en.wikibooks.org/wiki/Introduction_to_newLISP



All links are from this page:



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



... which also has a list of very nice video tutorials. Some of them for advanced topics like FOOP.



Many small applications and snippets:



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



In any case welcome to newLISP, I hope you stay with us a bit longer :)

gatesphere

#4
Thanks for all of those links, but I've read them already! :)



I'm aware that it's not CLISP or Scheme.  That's why I'm attracted to it.  I can't stand CLISP's bloat.



I was able to define an anaphoric if like this:


(define-macro (aif)
  (let ((it (eval (args 0))))
    (if it
      (eval (args 1))
      (eval (args 2)))))


And an example:


(aif (+ 23 42)
  (println it)
  (println "it's nil, bub."))


So it's a start.  I'm just exploring the idea of anaphora, and figured newLISP would be a good language to try it in.

johu

#5
self is a primitive function, then the variable name of self can't be used.



And previous labels's example cound not be used with closure.



(context 'MAIN:labels)
(define-macro (labels:labels)
  (letex (_labels (append '(begin)
                          (map (fn (x)
                                 (list 'setq (x 0) (append '(fn) (list (x 1)) (2 x))))
                            (args 0))
                          (1 (args))))
    _labels))
(context MAIN)

And alambda is



(define-macro (alambda)
  (letex (_funcbody (append '(_self) (list (args 0)) (1 (args))))
    (labels (_funcbody)
      _self)))

Then,



D:>newlisp -n
newLISP v.10.4.5 on Win32 IPv4/6 libffi, execute 'newlisp -h' for more info.

> self
self@40147C
> [cmd]
(context 'MAIN:labels)
(define-macro (labels:labels)
  (letex (_labels (append '(begin)
                          (map (fn (x)
                                 (list 'setq (x 0) (append '(fn) (list (x 1)) (2
 x))))
                            (args 0))
                          (1 (args))))
    _labels))
(context MAIN)
(define-macro (alambda)
  (letex (_funcbody (append '(_self) (list (args 0)) (1 (args))))
    (labels (_funcbody)
      _self)))
[/cmd]
labels
(lambda-macro ()
 (letex (_labels (append '(begin) (map (lambda (x) (list 'setq (x 0) (append '(l
ambda )
        (list (x 1))
        (2 x))))
     (args 0))
    (1 (args)))) _labels))
MAIN
(lambda-macro ()
 (letex (_funcbody (append '(_self) (list (args 0)) (1 (args)))) (labels (_funcb
ody)
   _self)))
> (set 'a (alambda (n) (if (= n 0) 1 (* n (_self (- n 1))))))
(lambda (n)
 (if (= n 0)
  1
  (* n (_self (- n 1)))))
> (a 3)
6
>

By the way

I rewrote codes of 'On Lisp' to newLISP.

If you are interested,

labels

http://johu02.wordpress.com/2010/06/19/">//http://johu02.wordpress.com/2010/06/19/

anaphoric macro

http://johu02.wordpress.com/2010/07/29/">//http://johu02.wordpress.com/2010/07/29/

But, Japanese, sorry.

William James

#6

> (set 'a (fn (n) (if (zero? n) 1 (* n (a (- n 1))))))
(lambda (n)
 (if (zero? n)
  1
  (* n (a (- n 1)))))
> (a 5)
120

rickyboy

#7
What Lutz is telling you and what William James is showing you is that you don't need constructs like flet or labels in newLISP, which only make sense (in fact, are necessary) in languages like Common Lisp where function names and variable names live in different namespaces.



This is not true in so-called Lisp-1 languages like newLISP and Scheme, so flet and labels are completely unnecessary in those languages.



Asking the question "is there something like flet or labels in newLISP?" is like walking around for years with your pockets full of coins so that you could use the public pay phones any time you needed them; and then one day you got a cell phone and asked the question, "Now that I have this cell phone -- an extra thing to put in my pockets - - what is a good way for me to continue to carry these coins?"
(λx. x x) (λx. x x)