Genlocal.

; In previous blogpost I defined gensym and genlet. If you didn't
; read it, read that post first.
;
; I'll repeat the definition of the gensym again, to remind my
; readers, and also, to allow evaluation of this post as a code.
; Also, I slightly improve name of my generated variables.



(set 'gensym-counter 0)

(set 'gensym
     (lambda(i)
       (inc gensym-counter)
       (sym (append "("
                    (string i)
                    " - "
                    (string gensym-counter)
                    ". generated symbol)"))))
                    
; genlet defined in the last post had same purpose as let, except
; it actually defined not variables, but generated versions of
; variables.

; Newlisp is, unlike other Lisp dialects, characterized with
; large number of constructs that implicitly define local variables.
; Beside let, there is a mighty letex, and also whole plethora
; of loops. All of these can have their own generated versions.
;
; But, there is one primitive in Newlisp that serves only to ensure
; that variables used inside that expression will be local. That is
; - expression local.

(set 'i 40)

(local(i)
  (println i)) ; Output => nil

; Just like local serves as general expression that can be wrapped
; around any other expression or list of expression to ensure
; they use local variables, we can define genlocal, which ensures
; that listed variables will be both generated and local.

; For example, genlocal call

;   (genlocal(a b c)
;      (set 'a 1)
;      (set 'b 2)
;      (set 'c 3))
;
     
;  should be transformed into
  
(letex((a (gensym 'a))
       (b (gensym 'b))
       (c (gensym 'c)))
       
   (first (list (local(a b c)
                      (set 'a 1)
                      (set 'b 2)
                      (set 'c 3))
      
                (begin (delete 'a)
                       (delete 'b)
                       (delete 'c)))))
                       

; It is very similar to definition of genlet from previous post,
; so I can almost cut and paste our previous macro:


(set 'genlocal
  (lambda-macro(head)
    (let ((body (args)))
         (letex  
                 ; look body first, head later.
         
                 ; head

                        ((H1 (map (lambda(x)
                                     (list x
                                           (list 'gensym
                                                 (list 'quote x))))
                                   head))
                                   
                          (H2 (cons 'local (cons head body)))
                          
                          
                          (H3 (cons 'begin (map (lambda(x)
                                                  (list 'delete
                                                        (list 'quote
                                                               x)))
                                                 head))))
                 ; body:
                 
                 (letex H1          
                     (first (list H2
                     
                                  H3)))))))
                                  

; I'll try that:

  (genlocal(a b c)
     (set 'a 1)
     (set 'b 2)
     (set 'c 3)
     (println 'a " = " a  "\n" 'b " = " b "\n" 'c " = " c))

; OUTPUT
;
; (a - 4. generated symbol) = 1
; (b - 5. generated symbol) = 2
; (c - 6. generated symbol) = 3
;

(exit)

No comments:

Post a Comment