Skip to content

Latest commit

 

History

History
109 lines (95 loc) · 3.95 KB

note.md

File metadata and controls

109 lines (95 loc) · 3.95 KB
  • there is another definition of letrec
(defmacro letrec-simple [bindings & body]
  (let [bcnt (quot (count bindings) 2)
        arrs (gensym "bindings_array")
        arrv `(make-array Object ~bcnt)
        bprs (partition 2 bindings)
        bssl (map first bprs)
        bsss (set bssl)
        bexs (map second bprs)
        arrm (zipmap bssl (range bcnt))
        btes (map #(clojure.walk/prewalk (fn [f]
                                   (if (bsss f)
                                     `(aget ~arrs ~(arrm f))
                                     f))
                                 %)
                  bexs)]
    `(let [~arrs ~arrv]
       ~@(map (fn [s e]
                `(aset ~arrs ~(arrm s) ~e))
              bssl
              btes)
       (let [~@(mapcat (fn [s]
                         [s `(aget ~arrs ~(arrm s))])
                       bssl)]
         ~@body))))
  • cause can not use auto gensym in nested syntax-quotes so use explicit gensym here
(let [x (gensym "x__")]
  `(let [~x 1]
     ~@(repeat 3
               `(println ~x))))
  • use destructure function to handle conditions below
(letrec [[ev? od?]
                [(fn [n] (if (zero? n) true (od? (dec n))))
                 (fn [n] (if (zero? n) false (ev? (dec n))))]]
         (ev? 10))
         
(letrec [[x y :as fibs]
                (cons 0 (cons 1 (lazy-seq (map + fibs (rest fibs)))))]
         [x y (take 10 fibs)])
         
(letrec [[f & fibs] (cons 0 (cons 1 (lazy-seq (map + (cons f fibs) fibs))))]
         (take 10 (cons f fibs)))
  • symbol macro defines a form that replaces a symbol during macro expansion. so use symbol-macrolet to handle the symbols inside the recursive definitions
(require [clojure.tools.macro :refer [mexpand-all]])

(mexpand-all '(letrec [y x
                       x 1]
                y))
=> (let*
    [letrec_bindings_array__6065 (clojure.core/make-array java.lang.Object 2)]
    (do
     (clojure.core/aset letrec_bindings_array__6065 0 (clojure.core/aget letrec_bindings_array__6065 1))
     (clojure.core/aset letrec_bindings_array__6065 1 1))
    (let* [y (clojure.core/aget letrec_bindings_array__6065 0) x (clojure.core/aget letrec_bindings_array__6065 1)] y))                 
      
;; symbol-macrolet will ignore quote reader macro
(mexpand-all '(letrec [y 'x
                       x 1]
                y))
=> (let*
    [letrec_bindings_array__6025 (clojure.core/make-array java.lang.Object 2)]
    (do (clojure.core/aset letrec_bindings_array__6025 0 (quote x)) (clojure.core/aset letrec_bindings_array__6025 1 1))
    (let* [y (clojure.core/aget letrec_bindings_array__6025 0) x (clojure.core/aget letrec_bindings_array__6025 1)] y))
      
;; if use letrec-simple
=> (let*
    [bindings_array6941 (clojure.core/make-array java.lang.Object 2)]
    (clojure.core/aset bindings_array6941 0 (quote (clojure.core/aget bindings_array6941 1)))
    (clojure.core/aset bindings_array6941 1 1)
    (let* [y (clojure.core/aget bindings_array6941 0) x (clojure.core/aget bindings_array6941 1)] y))
 
(mexpand-all '(letrec [y (delay x)
                       x 1]
               (force y)))
=> (let*
    [letrec_bindings_array__5934 (clojure.core/make-array java.lang.Object 2)]
    (do
     (clojure.core/aset
      letrec_bindings_array__5934
      0
      (new clojure.lang.Delay (fn* ([] (clojure.core/aget letrec_bindings_array__5934 1)))))
     (clojure.core/aset letrec_bindings_array__5934 1 1))
    (let*
     [y (clojure.core/aget letrec_bindings_array__5934 0) x (clojure.core/aget letrec_bindings_array__5934 1)]
     (force y)))
       
;; if use letrec-simple
=> (let*
    [letrec_bindings_array__5963 (clojure.core/make-array java.lang.Object 2)]
    (clojure.core/aset letrec_bindings_array__5963 0 (new clojure.lang.Delay (fn* ([] x))))
    (clojure.core/aset letrec_bindings_array__5963 1 1)
    (let*
     [y (clojure.core/aget letrec_bindings_array__5963 0) x (clojure.core/aget letrec_bindings_array__5963 1)]
     (force y)))