Permalink
Browse files

Added examples for 2nd half of chapter 7

  • Loading branch information...
Richard Hall Richard Hall
Richard Hall authored and Richard Hall committed May 3, 2012
1 parent 4e3b501 commit 0ae0cb1afc7d7dbc87cb7908e17e41b28752b766
Showing with 153 additions and 1 deletion.
  1. +1 −1 README.md
  2. +152 −0 src/OnLisp/ch7.clj
View
@@ -22,7 +22,7 @@ Contents
[Chapter 5](http://onbeyondlambda.blogspot.jp/2012/04/on-lisp-in-clojure-ch-5.html) - More advanced functional programming
[Chapter 6](http://onbeyondlambda.blogspot.com/2012/04/on-lisp-in-clojure-chapter-6.html) - Representing Networks in data and closures
[Chapter 7 (7.1 - 7.4)](http://onbeyondlambda.blogspot.com/2012/04/on-lisp-in-clojure-chapter-7-71-74.html) - Intro to macros
-
+[Chapter 7 (7.5 - 7.11)](http://onbeyondlambda.blogspot.com/2012/05/on-lisp-in-clojure-chapter-7-75-711.html) - Intro to macros pt. 2
Links
-----
View
@@ -101,3 +101,155 @@
`(clojure.pprint/pprint (macroexpand-1 '~expr)))
(mac (our-while (atom true) (println "side effect") "Value"))
+
+
+;; Section 7.5
+
+(let [[x [y] & z] ['a ['b] 'c 'd ]]
+ (list x y z))
+
+(doseq [x '(1 2 3)]
+ (println x))
+
+;; this follows the same pattern as Graham's function, but because
+;; map is lazy, it is never actually realized!
+(defmacro our-dolist [[lst & result] & body]
+ `(do (map ~@body ~lst)
+ ~@result))
+
+
+(macroexpand-1 (our-dolist [[1 2 3] ] #(println %)))
+(macroexpand-1 (our-dolist [[1 2 3] 4] #(println %)))
+
+(defmacro when-bind [[var expr] body]
+ `(let [~var ~expr]
+ (when ~var)
+ ~@body ))
+
+(when-bind [input "something"] (println input))
+
+;; Section 7.6
+(defmacro our-defmacro [name params & body]
+ `(defn ~name [~@params]
+ (do
+ ~@body)))
+
+(macroexpand-1 '(our-defmacro test [x] (println x)(+ x 2)))
+
+;; Section 7.7 Just because we can do a thing, it does not follow that we must do a thing
+
+;; our desired result
+(let [w 3 x 1 y 2 z nil]
+ (loop [x x y y]
+ (if (> x 10)
+ (do (println z) y )
+ (do
+ (println x)
+ (println y)
+ (recur (inc x) (inc y))))))
+
+
+;; the macro
+(defmacro our-looper [{:keys [initial-vals
+ body
+ loop-params
+ recursion-expr
+ exit-cond
+ exit-code
+ return-val]}]
+ `(let [~@initial-vals]
+ (loop [~@loop-params]
+ (if ~exit-cond
+ (do ~exit-code
+ ~return-val)
+ (do ~@body
+ (recur ~@recursion-expr))
+ ))))
+
+;; how to call it
+(our-looper {:initial-vals [w 3 x 1 y 2 z nil]
+ :body ((println x) (println y))
+ :loop-params [x x y y]
+ :recursion-expr ((inc x) (inc y))
+ :exit-cond (> x 10)
+ :exit-code (println z)
+ :return-val y})
+
+
+;; Section 7.8
+(defmacro our-and [& args]
+ (loop [lst args]
+ (cond
+ (= (count lst) 0) true
+ (= (count lst) 1) (first lst)
+ :else (if (first lst) (recur (rest lst)) false))))
+
+
+;; section 7.9
+;; if func a depends on func b and func b gets modified, func a knows about it
+;; if func c depends on macro d and macro d gets modified, func c doesn't know
+(defn func-a [input]
+ (+ input 1))
+
+(defn func-b []
+ (func-a 3))
+
+(func-b)
+;; 4
+
+(defn func-a [input]
+ (+ input 10))
+
+(func-b)
+;; 13
+
+
+(defmacro macro-c [input]
+ `(+ ~input 1))
+
+(defn func-d []
+ (macro-d 3))
+
+(func-d)
+;; 4
+
+(defmacro macro-c [input]
+ `(+ ~input 10))
+
+(func-d)
+;; 4
+
+;; Section 7.10
+(defn second-f [x]
+ (first (rest x)))
+
+(defmacro second-m [x]
+ `(first (rest ~x)))
+
+(defn noisy-second-f [x]
+ (println "Someone is taking a cadr")
+ (first (rest x)))
+
+(defmacro noisy-second-m [x]
+ `(do
+ (println "Someone is taking a cadr")
+ (first (rest ~x))))
+
+(defn sum-f [& args]
+ (apply + args))
+
+(defmacro sum-m [& args]
+ `(apply + (list ~@args)))
+
+(defmacro sum2-m [& args]
+ `(+ ~@args))
+
+
+(defn foo [x y z]
+ (list x (let [x y]
+ (list x z))))
+
+(defmacro foo-m [x y z]
+ `(list ~x
+ (let [x# ~y]
+ (list x# ~z))))

0 comments on commit 0ae0cb1

Please sign in to comment.