入門編/反復

Last-modified: 2017-05-08 (月) 15:45:31

リスト中の各要素に同じ処理をしたい場合や、特定の条件を満たすまで同じ処理を繰り返したい場合などには mapcar 関数、foreach 特殊フォーム、while 特殊フォーム、for 特殊フォーム、prog 特殊フォームを使います。

; 文字列のリスト names 中の各文字列の長さを要素とする整数のリストを生成する場合
(setq names '("Abe" "Oda" "Suzuki" "Takahashi" "Watanabe"))
(mapcar 'strlen names)
→ (3 3 6 9 8)
; 文字列のリスト names 中の各文字列に "-san" を連結した文字列を要素とする文字列のリストを生成する場合
(mapcar (lambda (n) (strcat n "-san")) names)
→ ("Abe-san" "Oda-san" "Suzuki-san" "Takahashi-san" "Watanabe-san")
; 長さが等しい二つの文字列リストの要素を順に連結した文字列を要素とする文字列リストを生成する場合
(setq prefs '("Hokkai" "Tokyo" "Aichi" "Oosaka" "Hiroshima" "Fukuoka"))
(setq tails '("-do" "-to" "-ken" "-fu" "-ken" "-ken"))
(mapcar 'strcat prefs tails)
→ ("Hokkai-do" "Tokyo-to" "Aichi-ken" "Oosaka-fu" "Hiroshima-ken" "Fukuoka-ken")
; 長さが等しいインスタンスオブジェクトのリスト座標値のリストについて、
; 各オブジェクトのプロパティ xy を与えた座標値リストの各座標値に設定する場合。
(setq instances (geGetSelectedSet))
(setq points '((1.3 0.9) (2.5 12.3) (37.8 24.3) ...))
; mapcar を使う例
; instances と points のリストの長さが違うと、エラーになります。
(mapcar (lambda (i p) (i~>xy = p)) instances points)
; while を使う例
; instances と points のリストで長さの短い方で繰り返し動作が制限されます。
(while (and instances points) ; どちらのリストにも残りの要素がある間...
  ((car instances)~>xy = (car points))
  (setq instances (cdr instances))
  (setq points (cdr points))
)
; 文字列のリスト names 中の各文字列を順番に出力する場合
(foreach n names
  (printf "%s\n" n)
)
; 数値のリスト values の要素を先頭から順に見ていって、数値が 4.7 以下の間、値を出力する
(setq values '(1.8 -5.3 2.6 12.7 3.1 -4.1 8.1))
; foreach と prog/return を使う例
(prog ()
  (foreach v values
    (unless (leqp v 4.7) (return)) ; 数値 ≦ 4.7 でなくなったら、foreach を抜ける
    (printf "%f\n" v)
  )
)
values → (1.8 -5.3 2.6 12.7 3.1 -4.1 8.1)
; while を使う例
; (変数 values の内容は書き換わる)
(while (leqp (car values) 4.7) ; 数値 ≦ 4.7 である間…
  (printf "%f\n" (car values))
  (setq values (cdr values))
)
values → (12.7 3.1 -4.1 8.1)
; 数値のリスト values の中で正の数である要素のみを残したリストを生成する場合
; foreach を使う例
(setq values '(1.8 -5.3 2.6 12.7 3.1 -4.1 8.1))
(let
  ((buffer nil))
  (foreach v values
    (when (plusp v) ; 数値が正の数である場合…
      (setq buffer (cons v buffer))
    )
  )
  (reverse buffer)
)
→ (1.8 2.6 12.7 3.1 8.1)
; 1 から 20 までの整数の平方根の合計を求める場合
(setq sum 0.0)
(for n 1 20
  (setq sum (plus sum (sqrt n)))
)
sum → 61.66597781141981