Skip to content
Newer
Older
100644 866 lines (650 sloc) 15.8 KB
7c720fe @cemerick dump of REPL interactions and other inline code snippets
cemerick authored Apr 2, 2012
1
2 ;-----
3 (defmacro foreach [[sym coll] & body]
4 `(loop [coll# ~coll]
5 (when-let [[~sym & xs#] (seq coll#)]
6 ~@body
7 (recur xs#))))
8 ;= #'user/foreach
9 (foreach [x [1 2 3]]
10 (println x))
11 ; 1
12 ; 2
13 ; 3
14
15
16
17 ;-----
18 (defmacro foo []
19 `(if (= 0 (rand-int 2))
20 (println "foo!))) ;; oops, forgot a closing quote
21 ;= #<Exception java.lang.Exception: EOF while reading string>
22
23
24
25 ;-----
26 (defmacro print-keyword [x]
27 `(println (keyword ~x)))
28 ;= #'user/print-keyword
29 (print-keyword "foo")
30 ; :foo
31 ;= nil
32
33
34 ;-----
35 (reverse-it (nltnirp "foo"))
36
37
38 ;-----
39 (println "foo")
40
41
42 ;-----
43 (require '(clojure [string :as str]
44 [walk :as walk]))
45
46 (defmacro reverse-it
47 [form]
48 (walk/postwalk #(if (symbol? %)
49 (symbol (str/reverse (name %)))
50 %)
51 form))
52
53
54 ;-----
55 (reverse-it
56 (qesod [gra (egnar 5)]
57 (nltnirp (cni gra))))
58 ; 1
59 ; 2
60 ; 3
61 ; 4
62 ; 5
63 ;= nil
64
65
66 ;-----
67 (macroexpand-1 '(reverse-it
68 (qesod [gra (egnar 5)]
69 (nltnirp (cni gra)))))
70 ;= (doseq [arg (range 5)]
71 ;= (println (inc arg)))
72
73
74 ;-----
75 (defn oops [arg] (frobnicate arg))
76 ;= #<CompilerException java.lang.Exception:
77 ;= Unable to resolve symbol: frobnicate in this context (NO_SOURCE_FILE:1)>
78
79
80 ;-----
81 (defmacro oops [arg] `(frobnicate ~arg))
82 ;= #'user/oops
83
84
85 ;-----
86 (oops 123)
87 ;= #<CompilerException java.lang.IllegalStateException:
88 ;= Var user/frobnicate is unbound. (NO_SOURCE_FILE:0)>
89
90
91 ;-----
92 (macroexpand-1 '(oops 123))
93 ;= (user/frobnicate 123)
94
95
96 ;-----
97 (macroexpand-1 '(reverse-it
98 (qesod [gra (egnar 5)]
99 (nltnirp (cni gra)))))
100 ;= (doseq [arg (range 5)]
101 ;= (println (inc arg)))
102
103 (pprint (macroexpand '(reverse-it
104 (qesod [gra (egnar 5)]
105 (nltnirp (cni gra))))))
106 ; (loop*
107 ; [seq_1647
108 ; (clojure.core/seq (range 5))
109 ; chunk_1648
110 ; nil
111 ; count_1649
112 ; (clojure.core/int 0)
113 ; i_1650
114 ; (clojure.core/int 0)]
115 ; (if
116 ; (clojure.core/< i_1650 count_1649)
117 ; (clojure.core/let
118 ; [arg (.nth chunk_1648 i_1650)]
119 ; (do (println (inc arg)))
120 ; (recur
121 ; seq_1647
122 ; chunk_1648
123 ; count_1649
124 ; (clojure.core/unchecked-inc i_1650)))
125 ; (clojure.core/when-let
126 ; [seq_1647 (clojure.core/seq seq_1647)]
127 ; (if
128 ; (clojure.core/chunked-seq? seq_1647)
129 ; (clojure.core/let
130 ; [c__3798__auto__ (clojure.core/chunk-first seq_1647)]
131 ; (recur
132 ; (clojure.core/chunk-rest seq_1647)
133 ; c__3798__auto__
134 ; (clojure.core/int (clojure.core/count c__3798__auto__))
135 ; (clojure.core/int 0)))
136 ; (clojure.core/let
137 ; [arg (clojure.core/first seq_1647)]
138 ; (do (println (inc arg)))
139 ; (recur
140 ; (clojure.core/next seq_1647)
141 ; nil
142 ; (clojure.core/int 0)
143 ; (clojure.core/int 0)))))))
144
145
146 ;-----
147 (macroexpand '(cond a b c d))
148 ;= (if a b (clojure.core/cond c d))
149
150
151 ;-----
152 (require '[clojure.walk :as w])
153
154 (w/macroexpand-all '(cond a b c d))
155 ;= (if a b (if c d nil))
156
157
158 ;-----
159 (w/macroexpand-all ''(when x a))
160 ;= (quote (if x (do a)))
161
162
163 ;-----
164 (defmacro hello
165 [name]
166 (list 'println name))
167
168 (macroexpand '(hello "Brian"))
169 ;= (println "Brian")
170
171
172 ;-----
173 (defmacro while
174 [test & body]
175 (list 'loop []
176 (concat (list 'when test) body)
177 '(recur)))
178
179
180 ;-----
181 (defmacro while
182 [test & body]
183 `(loop []
184 (when ~test
185 ~@body
186 (recur))))
187
188
189 ;-----
190 (def foo 123)
191 ;= #'user/foo
192 [foo (quote foo) 'foo `foo]
193 ;= [123 foo foo user/foo]
194
195
196 ;-----
197 (in-ns 'bar)
198
199 `foo
200 ;= bar/foo
201
202
203 ;-----
204 (ns baz (:require [user :as u]))
205
206 `map
207 ;= clojure.core/map
208 `u/foo
209 ;= user/foo
210 `foo
211 ;= baz/foo
212
213
214 ;-----
215 (list `map `println [foo])
216 ;= (clojure.core/map clojure.core/println [123])
217
218
219 ;-----
220 `(map println [~foo])
221 ;= (clojure.core/map clojure.core/println [123])
222
223 `(map println ~[foo])
224 ;= (clojure.core/map clojure.core/println [123])
225
226
227 ;-----
228 `(println ~(keyword (str foo)))
229 ;= (clojure.core/println :123)
230
231
232 ;-----
233 (let [defs '((def x 123)
234 (def y 456))]
235 (concat (list 'do) defs))
236 ;= (do (def x 123) (def y 456))
237
238
239 ;-----
240 (let [defs '((def x 123)
241 (def y 456))]
242 `(do ~@defs))
243 ;= (do (def x 123) (def y 456))
244
245
246 ;-----
247 (defmacro foo
248 [& body]
249 `(do-something ~@body))
250
251 (macroexpand-1 '(foo (doseq [x (range 5)]
252 (println x))
253 :done))
254 ;= (user/do-something
255 ;= (doseq [x (range 5)]
256 ;= (println x))
257 ;= :done)
258
259
260 ;-----
261 '`(map println ~[foo])
262 ;= (clojure.core/seq
263 ;= (clojure.core/concat
264 ;= (clojure.core/list (quote clojure.core/map))
265 ;= (clojure.core/list (quote clojure.core/println))
266 ;= (clojure.core/list [foo])))
267
268
269 ;-----
270 (defn fn-hello [x]
271 (str "Hello, " x "!"))
272
273 (defmacro macro-hello [x]
274 `(str "Hello, " ~x "!"))
275
276
277 ;-----
278 (fn-hello "Brian")
279 ;= "Hello, Brian!"
280 (macro-hello "Brian")
281 ;= "Hello, Brian!"
282
283
284 ;-----
285 (map fn-hello ["Brian" "Not Brian"])
286 ;= ("Hello, Brian!" "Hello, Not Brian!")
287 (map macro-hello ["Brian" "Not Brian"])
288 ;= #<CompilerException java.lang.RuntimeException:
289 ;= Can't take value of a macro: #'user/macro-hello, compiling:(NO_SOURCE_PATH:1)>
290
291
292 ;-----
293 (map #(macro-hello %) ["Brian" "Not Brian"])
294 ;= ("Hello, Brian!" "Hello, Not Brian!")
295
296
297 ;-----
298 (defmacro unhygienic
299 [& body]
300 `(let [x :oops]
301 ~@body))
302 ;= #'user/unhygenic
303 (unhygienic (println "x:" x))
304 ;= #<CompilerException java.lang.RuntimeException:
305 ;= Can't let qualified name: user/x, compiling:(NO_SOURCE_PATH:1)>
306
307
308 ;-----
309 (macroexpand-1 `(unhygienic (println "x:" x)))
310 ;= (clojure.core/let [user/x :oops]
311 ;= (clojure.core/println "x:" user/x))
312
313
314 ;-----
315 (defmacro still-unhygienic
316 [& body]
317 `(let [~'x :oops]
318 ~@body))
319 ;= #'user/still-unhygenic
320 (still-unhygienic (println "x:" x))
321 ; x: :oops
322 ;= nil
323 (macroexpand-1 '(still-unhygienic
324 (println "x:" x)))
325 ;= (clojure.core/let [x :oops]
326 ;= (println "x:" x))
327
328
329 ;-----
330 (let [x :this-is-important]
331 (still-unhygienic
332 (println "x:" x)))
333 ; x: :oops
334
335
336 ;-----
337 (gensym)
338 ;= G__2386
339 (gensym)
340 ;= G__2391
341
342
343 ;-----
344 (gensym "sym")
345 ;= sym2396
346 (gensym "sym")
347 ;= sym2402
348
349
350 ;-----
351 (defmacro hygienic
352 [& body]
353 (let [sym (gensym)]
354 `(let [~sym :macro-value]
355 ~@body)))
356 ;= #'user/hygienic
357 (let [x :important-value]
358 (hygienic (println "x:" x)))
359 ; x: :important-value
360 ;= nil
361
362
363 ;-----
364 (defmacro hygienic
365 [& body]
366 `(let [x# :macro-value]
367 ~@body))
368
369
370 ;-----
371 `(x# x#)
372 ;= (x__1447__auto__ x__1447__auto__)
373
374
375 ;-----
376 (defmacro auto-gensyms
377 [& numbers]
378 `(let [x# (rand-int 10)]
379 (+ x# ~@numbers)))
380 ;= #'user/auto-gensyms
381 (auto-gensyms 1 2 3 4 5)
382 ;= 22
383 (macroexpand-1 '(auto-gensyms 1 2 3 4 5))
384 ;= (clojure.core/let [x__570__auto__ (clojure.core/rand-int 10)]
385 ;= (clojure.core/+ x__570__auto__ 1 2 3 4 5))
386
387
388 ;-----
389 [`x# `x#]
390 ;= [x__1450__auto__ x__1451__auto__]
391
392
393 ;-----
394 (defmacro our-doto [expr & forms]
395 `(let [obj# ~expr]
396 ~@(map (fn [[f & args]]
397 `(~f obj# ~@args)) forms)
398 obj#))
399
400
401 ;-----
402 (our-doto "It works"
403 (println "I can't believe it"))
404 ;= #<CompilerException java.lang.RuntimeException:
405 ;= Unable to resolve symbol: obj__1456__auto__ in this context,
406 ;= compiling:(NO_SOURCE_PATH:1)>
407
408
409 ;-----
410 (defmacro our-doto [expr & forms]
411 (let [obj (gensym "obj")]
412 `(let [~obj ~expr]
413 ~@(map (fn [[f & args]]
414 `(~f ~obj ~@args)) forms)
415 ~obj)))
416
417
418 ;-----
419 (our-doto "It works"
420 (println "I can't believe it")
421 (println "I still can't believe it"))
422 ; It works I can't believe it
423 ; It works I still can't believe it
424 ;= "It works"
425
426
427 ;-----
428 (defmacro with
429 [name & body]
430 `(let [~name 5]
431 ~@body))
432 ;= #'user/with
433 (with bar (+ 10 bar))
434 ;= 15
435 (with foo (+ 40 foo))
436 ;= 45
437
438
439 ;-----
440 (defmacro spy [x]
441 `(do
442 (println "spied" '~x ~x)
443 ~x))
444
445
446 ;-----
447 (spy 2)
448 ; spied 2 2
449 ;= 2
450 (spy (rand-int 10))
451 ; spied (rand-int 10) 9
452 ;= 7
453
454
455 ;-----
456 (macroexpand-1 '(spy (rand-int 10)))
457 ;= (do (println (rand-int 10))
458 ;= (rand-int 10))
459
460
461 ;-----
462 (defmacro spy [x]
463 `(let [x# ~x]
464 (println "spied" '~x x#)
465 x#))
466
467 (macroexpand-1 '(spy (rand-int 10)))
468 ;= (let [x__725__auto__ (rand-int 10)]
469 ;= (println x__725__auto__ '(rand-int 10))
470 ;= x__725__auto__)
471
472
473 ;-----
474 (spy (rand-int 10))
475 ; spied (rand-int 10) 9
476 ;= 9
477
478
479 ;-----
480 (defn spy-helper [expr value]
481 (println expr value)
482 value)
483
484 (defmacro spy [x]
485 `(spy-helper '~x ~x))
486
487
488 ;-----
489 (let [a 42
490 b "abc"]
491 ...)
492
493 (if-let [x (test)]
494 then
495 else)
496
497 (with-open [in (input-stream ...)
498 out (output-stream ...)]
499 ...)
500
501 (for [x (range 10)
502 y (range x)]
503 [x y])
504
505
506 ;-----
507 (defmacro spy-env []
508 (let [ks (keys &env)]
509 `(prn (zipmap '~ks [~@ks]))))
510
511 (let [x 1 y 2]
512 (spy-env)
513 (+ x y))
514 ; {x 1, y 2}
515 ;= 3
516
517
518 ;-----
519 (defmacro simplify
520 [expr]
521 (let [locals (set (keys &env))]
522 (if (some locals (flatten expr))
523 expr
524 (do
525 (println "Precomputing: " expr)
526 (list `quote (eval expr))))))
527
528
529 ;-----
530 (defn f
531 [a b c]
532 (+ a b c (simplify (apply + (range 5e7)))))
533 ; Precomputing: (apply + (range 5e7))
534 ;= #'user/f
535 (f 1 2 3) ;; returns instantly
536 ;= 1249999975000006
537 (defn f'
538 [a b c]
539 (simplify (apply + a b c (range 5e7))))
540 ;= #'user/f'
541 (f' 1 2 3) ;; takes ~2.5s to calculate
542 ;= 1249999975000006
543
544
545 ;-----
546 (@#'simplify nil {} '(inc 1))
547 ; Precomputing: (inc 1)
548 ;= (quote 2)
549 (@#'simplify nil {'x nil} '(inc x))
550 ;= (inc x)
551
552
553 ;-----
554 (defmacro ontology
555 [& triples]
556 (every? #(or (== 3 (count %))
557 (throw (IllegalArgumentException.
558 "All triples provided as arguments must have 3 elements")))
559 triples)
560 ;; build and emit pre-processed ontology here...
561 )
562
563
564 ;-----
565 (ontology ["Boston" :capital-of])
566 ;= #<IllegalArgumentException java.lang.IllegalArgumentException:
567 ;= All triples provided as arguments must have 3 elements>
568 (pst)
569 ;= IllegalArgumentException All triples provided as arguments must have 3 elements
570 ;= user/ontology (NO_SOURCE_FILE:3)
571
572
573 ;-----
574 (defmacro ontology
575 [& triples]
576 (every? #(or (== 3 (count %))
577 (throw (IllegalArgumentException.
578 (format "Vector `%s` provided to `%s` on line %s does not have 3 elements"
579 %
580 (first &form)
581 (-> &form meta :line)))))
582 triples)
583 ;; ...
584 )
585
586
587 ;-----
588 (ontology ["Boston" :capital-of])
589 ;= #<IllegalArgumentException java.lang.IllegalArgumentException:
590 ;= Vector `["Boston" :capital-of]` provided to `ontology` on line 1 does not have 3 elements>
591
592
593 ;-----
594 (ns com.clojurebook.macros)
595 ;= nil
596 (refer 'user :rename '{ontology triples})
597 ;= nil
598
599
600 ;-----
601 (triples ["Boston" :capital-of])
602 ;= #<IllegalArgumentException java.lang.IllegalArgumentException:
603 ;= Vector `["Boston" :capital-of]` provided to `triples` on line 1 does not have 3 elements>
604
605
606 ;-----
607 (set! *warn-on-reflection* true)
608 ;= true
609 (defn first-char-of-either
610 [a b]
611 (.substring ^String (or a b) 0 1))
612 ; Reflection warning, NO_SOURCE_PATH:2 - call to substring can't be resolved.
613 ;= #'user/first-char-of-either
614
615
616 ;-----
617 (defn first-char-of-either
618 [^String a ^String b]
619 (.substring (or a b) 0 1))
620 ;= #'user/first-char-of-either
621
622
623 ;-----
624 (binding [*print-meta* true]
625 (prn '^String (or a b)))
626 ; ^{:tag String, :line 1} (or a b)
627
628
629 ;-----
630 (binding [*print-meta* true]
631 (prn (macroexpand '^String (or a b))))
632 ; (let* [or__3548__auto__ a]
633 ; (if or__3548__auto__ or__3548__auto__ (clojure.core/or b)))
634
635
636 ;-----
637 (defmacro or
638 ([] nil)
639 ([x] x)
640 ([x & next]
641 `(let [or# ~x]
642 (if or# or# (or ~@next)))))
643
644
645 ;-----
646 (defmacro OR
647 ([] nil)
648 ([x]
649 (let [result (with-meta (gensym "res") (meta &form))]
650 `(let [~result ~x]
651 ~result)))
652 ([x & next]
653 (let [result (with-meta (gensym "res") (meta &form))]
654 `(let [or# ~x
655 ~result (if or# or# (OR ~@next))]
656 ~result))))
657
658
659 ;-----
660 (binding [*print-meta* true]
661 (prn (macroexpand '^String (OR a b))))
662 ; (let* [or__1176__auto__ a
663 ; ^{:tag String, :line 2}
664 ; res1186 (if or__1176__auto__ or__1176__auto__ (user/or b))]
665 ; ^{:tag String, :line 2} res1186)
666
667
668 ;-----
669 (defn first-char-of-any
670 [a b]
671 (.substring ^String (OR a b) 0 1))
672 ;= #'user/first-char-of-any
673
674
675 ;-----
676 (defn preserve-metadata
677 "Ensures that the body containing `expr` will carry the metadata
678 from `&form`."
679 [&form expr]
680 (let [res (with-meta (gensym "res") (meta &form))]
681 `(let [~res ~expr]
682 ~res)))
683
684 (defmacro OR
685 "Same as `clojure.core/or`, but preserves user-supplied metadata
686 (e.g. type hints)."
687 ([] nil)
688 ([x] (preserve-metadata &form x))
689 ([x & next]
690 (preserve-metadata &form `(let [or# ~x]
691 (if or# or# (or ~@next))))))
692
693
694 ;-----
695 ^long (deep-aget aa 0 0)
696
697
698 ;-----
699 (defmacro deep-aget
700 ([array-expr i]
701 (let [tag ('{int ints float float long longs double doubles
702 byte bytes char chars boolean booleans nil nil}
703 (-> &form meta :tag) 'objects)]
704 (with-meta `(aget ~(vary-meta array-expr assoc :tag tag) ~i)
705 (meta &form))))
706 ([array-expr i & js]
707 (with-meta
708 `(deep-aget ^Object (deep-aget ~array-expr ~i) ~@js)
709 (meta &form))))
710
711
712 ;-----
713 (defn macroexpand1-env [env form]
714 (if-let [[x & xs] (and (seq? form) (seq form))]
715 (if-let [v (and (symbol? x) (resolve x))]
716 (if (-> v meta :macro)
717 (apply @v form env xs)
718 form)
719 form)
720 form))
721
722
723 ;-----
724 (macroexpand1-env '{} '(simplify (range 10)))
725 ; Precomputing: (range 10)
726 ;= (quote (0 1 2 3 4 5 6 7 8 9))
727 (macroexpand1-env '{range nil} '(simplify (range 10)))
728 ;= (range 10)
729
730
731 ;-----
732 (defmacro spy [expr]
733 `(let [value# ~expr]
734 (println (str "line #" ~(-> &form meta :line) ",")
735 '~expr value#)
736 value#))
737 ;= #'user/spy
738 (let [a 1
739 a (spy (inc a))
740 a (spy (inc a))]
741 a)
742 ; line #2, (inc a) 2
743 ; line #3, (inc a) 3
744 ;= 3
745
746
747 ;-----
748 (macroexpand1-env {} (with-meta '(spy (+ 1 1)) {:line 42}))
749 ;= (clojure.core/let [value__602__auto__ (+ 1 1)]
750 ;= (clojure.core/println
751 ;= (clojure.core/str "line #" 42 ",")
752 ;= (quote (+ 1 1)) value__602__auto__)
753 ;= value__602__auto__)
754
755
756 ;-----
757 (defn macroexpand1-env [env form]
758 (if-all-let [[x & xs] (and (seq? form) (seq form))
759 v (and (symbol? x) (resolve x))
760 _ (-> v meta :macro)]
761 (apply @v form env xs)
762 form))
763
764
765 ;-----
766 (defmacro if-all-let [bindings then else]
767 (reduce (fn [subform binding]
768 `(if-let [~@binding] ~subform ~else))
769 then (reverse (partition 2 bindings))))
770
771
772 ;-----
773 (prn (conj (reverse [1 2 3]) 4))
774
775
776 ;-----
777 (thread [1 2 3] reverse (conj 4) prn)
778
779
780 ;-----
781 (-> foo (bar) (baz))
782
783
784 ;-----
785 (-> foo bar baz)
786
787
788 ;-----
789 (defn ensure-seq [x]
790 (if (seq? x) x (list x)))
791
792 (ensure-seq 'x)
793 ;= (x)
794 (ensure-seq '(x))
795 ;= (x)
796
797
798 ;-----
799 (defn insert-second
800 "Insert x as the second item in seq y."
801 [x ys]
802 (let [ys (ensure-seq ys)]
803 (concat (list (first ys) x)
804 (rest ys))))
805
806
807 ;-----
808 (defn insert-second
809 "Insert x as the second item in seq y."
810 [x ys]
811 (let [ys (ensure-seq ys)]
812 `(~(first ys) ~x ~@(rest ys))))
813
814
815 ;-----
816 (defn insert-second
817 "Insert x as the second item in seq y."
818 [x ys]
819 (let [ys (ensure-seq ys)]
820 (list* (first ys) x (rest ys))))
821
822
823 ;-----
824 (defmacro thread
825 "Thread x through successive forms."
826 ([x] x)
827 ([x form] (insert-second x form))
828 ([x form & more] `(thread (thread ~x ~form) ~@more)))
829
830
831 ;-----
832 (thread [1 2 3] (conj 4) reverse println)
833 ;= (4 3 2 1)
834 (-> [1 2 3] (conj 4) reverse println)
835 ;= (4 3 2 1)
836
837
838 ;-----
839 (defn thread-fns
840 ([x] x)
841 ([x form] (form x))
842 ([x form & more] (apply thread-fns (form x) more)))
843
844 (thread-fns [1 2 3] reverse #(conj % 4) prn)
845 ;= (4 3 2 1)
846
847
848 ;-----
849 (thread [1 2 3] .toString (.split " ") seq)
850 ;= ("[1" "2" "3]")
851
852 (thread-fns [1 2 3] .toString #(.split % " ") seq)
853 ;= #<CompilerException java.lang.RuntimeException:
854 ;= Unable to resolve symbol: .toString in this context, compiling:(NO_SOURCE_PATH:1)>
855
856 ;; This is starting to look a bit hairy...
857 (thread-fns [1 2 3] #(.toString %) #(.split % " ") seq)
858 ;= ("[1" "2" "3]")
859
860
861 ;-----
862 (->> (range 10) (map inc) (reduce +))
863 ;= 55
864
865
Something went wrong with that request. Please try again.