今までloopマクロを怖がって避けてたけど、つかってみたら結構便利だった。
1から10までの数を集める
(require 'cl) (loop for i from 1 to 10 collect i); =>(1 2 3 4 5 6 7 8 9 10)
collectを使うとlistに集めていくような処理になるみたい
他にもappend,nconc,sum,count,doがある
(defmacro 1from10 (action var expr) `(loop for ,var from 1 to 10 ,action ,expr)) (1from10 collect i (* i i)); =>(1 4 9 16 25 36 49 64 81 100) (1from10 sum i (* i i));; =>385 (1from10 count i (oddp i)); =>5 ;;appendとnconcも同じような感じ ;;あとdoは任意の式をじっこうできる (1from10 do i (princ i))
増加する値を増やしたい時にはbyを使う
(loop for i from 0 to 100 by 10 collect i);; =>(0 10 20 30 40 50 60 70 80 90 100)
リスト内包表記みたいにfilterを掛けながら使うこともできる
;;ifを使って (loop for i from 0 to 10 if (oddp i) collect i); =>(1 3 5 7 9) ;;unlessもある (loop for i from 0 to 10 unless (zerop (mod i 3)) collect i); =>(1 2 4 5 7 8 10)
for=で途中の値を束縛しておける
(loop for i from 1 to 3 for sq = (* i i) collect sq); =>(1 4 9)
listのiteratorとして使うこともできる
;;何か要素を持ったリストを作成 (setq l (loop for i from 0 to 5 for sq = (* i i) collect (cons i sq))) ;; =>((0 . 0) (1 . 1) (2 . 4) (3 . 9) (4 . 16) (5 . 25)) ;;inを使ってリストの要素を順にたどることができる (loop for elt in l if (oddp (car elt)) collect elt); =>((1 . 1) (3 . 9) (5 . 25)) ;;destructure-bindに近いこともできる (loop for (i . sq) in l if (> sq 10) collect (list i (list sq))); =>((4 (16)) (5 (25)))
リスト操作とかをしたければこれくらい覚えれば十分な気がする。
最後に
あとは、
- initiallyとfinallyを使って最初と最後の処理を書ける
- whileで条件が真の間だけloopできる
- withでloop内の変数を作成することができる。
- returnで返す値を指定できる
ということを使えば、現在のbuffer中の"for"の数を数える処理とかが簡単に書ける
(save-excursion (loop initially (goto-char (point-min)) with count = 0 while (re-search-forward "for" nil t 1) do (incf count) finally return count)); =>19 ;;他にもこんな書き方も (save-excursion (loop initially (goto-char (point-min)) while (re-search-forward "for" nil t 1) count t));; =>19 ;;loopを使わないとこんな感じかな? (let ((count 0)) (save-excursion (goto-char (point-min)) (while (re-search-forward "for" nil t 1) (incf count)) count));; =>19
あまり複雑なことをしようと思わなければloopは難しくない。
今度からもっとloopを使うようにしよう。