-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathch8.lisp
More file actions
66 lines (49 loc) · 2.1 KB
/
ch8.lisp
File metadata and controls
66 lines (49 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
; MACROS
;; The key to understanding macros is to be quite clear
;;about the distinction between the code that generates code (macros)
;; and the code that eventually makes up the program (everything else).
;; (defmacro name (parameter*)
;; "Optional documentation string."
;; body-form*)
(defun primep (number)
(when (> number 1)
(loop for fac from 2 to (isqrt number) never (zerop (mod number fac)))))
(defun next-prime (number)
(loop for n from number when (primep n) return n))
;; we want to make this work,
; i.e, give me all primes between 0 and 19
(defmacro do-primes (var-and-range &rest body)
(let ((var (first var-and-range))
(start (second var-and-range))
(end (third var-and-range)))
`(do ((, var (next-prime ,start) (next-prime (1+, var))))
((> ,var ,end))
,@body)))
(do-primes p 0 19)
(format t "~d " p)
;; doing this with (do)
(do ((p (next-prime 0) (next-prime (1+ p))))
((> p 19))
(format t "~d " p))
;; a shorter version of (do-primes) macro
(defmacro do-primes ((var start end) &body body)
`(do ((,var (next-prime ,start) (next-prime (1+ ,var)))
(ending-value ,end))
((> ,var ending-value))
,@body))
;; gensym can be used to generate unique symbols in macros so that there's no collision between the name of the
;; parameter/variable and the name of the variable in the body of the macro
; here's a gensym version of the do-primes macro
(defmacro do-primes ((var start end) &body body)
(let ((ending-value (gensym)))
`(do ((,var (next-prime ,start) (next-prime (1+ ,var)))
(,ending-value ,end))
((> ,var ,ending-value))
,@body)))
;; Break 15 [17]> (macroexpand-1 '(do-primes (ending-value 0 (random 100))))
; (DO ((ENDING-VALUE (NEXT-PRIME 0) (NEXT-PRIME (1+ ENDING-VALUE))) (#:G3141 (RANDOM 100))) ((> ENDING-VALUE #:G3141))) ;
; T
; the real form of creating a macro if possibles takes the following form...
; (defmacro name ((var start end) &body body)
; (let ((some-var (gensym)))
; `(some-form ,var ,start ,end ,some-var ,@body)))