Genloops.

; In third post in this "generated" serial, I'll define "generated"
; versions of loops. By generated, I mean that you use them as
; normal loops, and they substitute normal symbols with generated
; symbols.
;
; The loops for, doargs, dolist, dostring, dotimes and dotree have
; same syntax:
;
;              (<loopname> (<symbol> ...) body)
;
;
; I'll try to define genfor, gendoargs, gendolist, gendostring and
; gendotimes so they are used on the following way:
;
;
;              (gen<loopname> (<symbol> ...) <body>)
;                 ^
;                 |
;                only "gen" is inserted, analogously to gensym.
;
;
; Such "generated loops" should be evaluated like
;
;
;              (genlocal(<symbol>)
;                      (<loopname>(<symbol> ...) <body>))
;
;
; Definitions of gensym and genlocal pasted from previous post:


        (set 'gensym-counter 0)

        (set 'gensym
             (lambda(i)
               (inc gensym-counter)
               (sym (append "("
                            (string i)
                            " - "
                            (string gensym-counter)
                            ". generated symbol)"))))

        (set 'genlocal
          (lambda-macro(head)
            (let ((body (args)))
                 (letex ((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))))
                         (letex H1          
                             (first (list H2
                                          H3)))))))


; Definition of "generated loops" genfor, gendoarg, gendolist,
; gendostring, gendotimes so they behave like described above.
; Again, code is complicated but technical, but idea is important.

(dolist (loopname '(for doargs dolist dostring dotimes))
  (set (sym (append "gen" (string loopname))) ; for -> genfor etc
       
       (letex ((loopname loopname))
         (lambda-macro(head)
           (let ((body (args)))
             (letex((H1 (list (first head)))
                    (H2 (append (list 'loopname head) body)))
                   (genlocal H1
                             H2)))))))
                             
                                  
; Next, I'll memorize (symbols), to show that that all generated
; symobls will be actually, cleaned.

(set 'symbols-before-genloops (symbols))

; Tests that new genfors really work:
                                     
(genfor (i 10 20 5)
        (println 'i " = " i))
        
(println)

(gendolist (j '(a b c))
           (println 'j " = " j))
           
(println)

(gendotimes(k 4)(println 'k " = " k))

(println)

; OUTPUT

; (i - 1. generated symbol) = 10
; (i - 1. generated symbol) = 15
; (i - 1. generated symbol) = 20

; (j - 2. generated symbol) = a
; (j - 2. generated symbol) = b
; (j - 2. generated symbol) = c

; (k - 3. generated symbol) = 0
; (k - 3. generated symbol) = 1
; (k - 3. generated symbol) = 2
; (k - 3. generated symbol) = 3


; Test that gensyms are deleted:

(println (difference (symbols) symbols-before-genloops))

; OUTPUT
;
; (a b c j k)
;
; OK.

(exit)

No comments:

Post a Comment