loopの奥深さを知る
loopマクロってほんとにすごい。究極の言語内DSL。ここまでくるともう芸術品としか言えない。
loopをキモいと言うLisperは多そうだけど、それが設計できるのがLispなんだろう。
いろいろな例をREPLで実行中。結果は後でさっと見られるようにusage-memoに書いておく。
;; for = as (defun at-most-3times (list) (loop for item in list for i from 1 to 3 collect (format nil "<~a>" item))) (at-most-3times '(1 2 3 4)) ; ("<1>" "<2>" "<3>") (at-most-3times '(1 2)) ; ("<1>" "<2>") ;; from downfrom upfrom ;; to upto below downto above ;; by (loop for i from 1 to 3 collecting i) ; (1 2 3) (loop for i from 1 to 5 by 2 collect i) ; (1 3 5) ;; 0-origin (loop for i upto 10 collect i) ; (0 1 2 3 4 5 6 7 8 9 10) (loop for i to 10 collect i) ; (0 1 2 3 4 5 6 7 8 9 10) (loop for i from 0 downto -10 collect i) ; (0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10) (loop for i below 10 collect i) ; (0 1 2 3 4 5 6 7 8 9) (loop for i from 0 above -10 collect i) ; (0 -1 -2 -3 -4 -5 -6 -7 -8 -9) (loop repeat 3 collect 1) ; (1 1 1) (loop for i in '(10 20) collect (* i 9)) ; (90 180) (loop for i in '(10 20 30 40) collect i) ; (10 20 30 40) (loop for i in '(10 20 30 40) by #'cdr collect i) ; (10 20 30 40) (loop for i in '(10 20 30 40) by #'cddr collect i) ; (10 30) (loop for i on '(10 20 30 40) collect i) ; ((10 20 30 40) (20 30 40) (30 40) (40)) (loop for i on '(10 20 30 40) by #'cdr collect i) ; ((10 20 30 40) (20 30 40) (30 40) (40)) (loop for i on '(10 20 30 40) by #'cddr collect i) ; ((10 20 30 40) (30 40)) (loop for x across "abcd" collect x) ; (#\a #\b #\c #\d) ;; the = each / of = in / singular ;; for var being the hash-keys in hash ;; for var being the hash-values in hash ;; for var being the symbols in package ;; for var being the present-symbols in package ;; for var being the external-symbols in package ;; 長っ!! (loop for k being the hash-keys in hash using (hash-values v) ...) (loop for v being the hash-values in hash using (hash-key k) ...) ;; do* みたいなの ;; x: 0 1 2 4 8 ;; y: 1 2 4 8 16 (loop repeat 5 for x = 0 then y for y = 1 then (+ x y) collect (cons x y)) ; ((0 . 1) (1 . 2) (2 . 4) (4 . 8) (8 . 16)) ;; y: 1 1 2 4 8 ;; x: 0 1 2 4 8 (loop repeat 5 for y = 1 then (+ x y) for x = 0 then y collect (cons x y)) ; ((0 . 1) (1 . 1) (2 . 2) (4 . 4) (8 . 8)) ;; do みたいなの fibonacci ;; x: 0 1 1 2 3 ;; y: 1 1 2 3 5 (loop repeat 5 for x = 0 then y and y = 1 then (+ x y) collect y) ; (1 1 2 3 5) ;; with var = expr ;; destructing (loop for (a b) in '((1 2)(3 4)(5 6)) collect (format nil "a:~a, b:~a" a b)) ; ("a:1, b:2" "a:3, b:4" "a:5, b:6") ;; collect, append, nconc, count, sum, maximize, minimize ;; return ;; finally ;; when, if, unless (loop for x from 1 to 4 when (evenp x) sum x) ; 6 (loop for x from 1 to 4 if (evenp x) sum x) ; 6 (loop for x from 1 to 4 unless (evenp x) sum x) ; 4 ;; it (loop for key in some-list when (gethash key some-hash) collect it) ;; named (loop named outer for list in lists do (loop for item in list do (if (what-i-am-looking-for-p item) (return-from outer item)))) ;; initially, finally ;; while, until, always, never, thereis (loop for n in '(2 4 6) always (evenp n)) ; T (loop for n in '(2 4 6) never (oddp n)) ; T (loop for char across "abc123" thereis (digit-char-p char)) ; 1 (loop for char across "abcdef" thereis (digit-char-p char)) ; NIL