7.8.3-dolist-dotimes.lisp (1740B)
1 (defmacro my-dolist (spec &rest body) 2 (let ((var (car spec)) 3 (listform (cadr spec)) 4 (resultform (caddr spec)) 5 (loopsym (make-symbol "loop")) 6 (endsym (make-symbol "end")) 7 (listsym (make-symbol "list"))) 8 `(let ((,var nil) 9 (,listsym ,listform)) 10 (tagbody 11 ,loopsym 12 (setq ,var (car ,listsym)) 13 (when (endp ,listsym) 14 (go ,endsym)) 15 (progn ,@body) 16 (setq ,listsym (cdr ,listsym)) 17 (go ,loopsym) 18 ,endsym) 19 ,resultform))) 20 21 ;; (let ((foo 42)) (my-dolist (a '(1 2 3) foo) (print a))) 22 ;; => 1 23 ;; => 2 24 ;; => 3 25 ;; => 42 26 ;; (my-dolist (a '(1 2 3)) (print a)) 27 ;; => 1 28 ;; => 2 29 ;; => 3 30 ;; => nil 31 ;; (my-dolist (a '(1 2 3) a) (print a)) 32 ;; => 1 33 ;; => 2 34 ;; => 3 35 ;; => nil 36 ;; (my-dolist (a '()) (print a)) 37 ;; => nil 38 39 (defmacro my-dotimes (spec &rest body) 40 (let ((var (car spec)) 41 (countform (cadr spec)) 42 (resultform (caddr spec)) 43 (loopsym (make-symbol "loop")) 44 (endsym (make-symbol "end")) 45 (countersym (make-symbol "counter")) 46 (maxsym (make-symbol "max"))) 47 `(let ((,var nil) 48 (,maxsym ,countform) 49 (,countersym 0)) 50 (tagbody 51 ,loopsym 52 (setq ,var ,countersym) 53 (when (>= ,countersym ,maxsym) 54 (go ,endsym)) 55 (progn ,@body) 56 (setq ,countersym (+ ,countersym 1)) 57 (go ,loopsym) 58 ,endsym 59 (when (< 0 ,var) (setq ,var 0))) 60 ,resultform))) 61 62 ;; (my-dotimes (i 3) (print i)) 63 ;; => 0 64 ;; => 1 65 ;; => 2 66 ;; => nil 67 ;; (my-dotimes (i 3 i) (print i)) 68 ;; => 0 69 ;; => 1 70 ;; => 2 71 ;; => 3 72 ;; (my-dotimes (i -5 i) (print i)) 73 ;; => 0 74 ;; (my-dotimes (i -5) (print i)) 75 ;; => nil