2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【復刻版】黒帯のためのLOOP(2)

Last updated at Posted at 2022-12-19

はじめに

この連載ではCommon LispのLOOPマクロをサンプルを使って紹介する。
LOOPマクロは (cl-loopを用いることで) Emacs Lispでも利用可能である。

Common Lisp: loopマクロ用法抄より引用】

Grahamの ANSI Common Lisp では嫌われていて碌に説明のないloopマクロ。一方、 実践Common Lisp では対照的に好んで用いられていて、全編に渡って頻繁に使われている。しかしloopマクロは難しいという意識があるのかその説明は第22章とかなり後回しにされており、ちぐはぐな感を受ける。ここでは、 黒帯のためのLOOP という題のつけられたその章で解説されているloopマクロの用法を整理してみた。

ANSI Common Lisp での黒魔術扱いに敬遠していたloopマクロだったが、こうして整理してみるとそれほど難しく考えずとも便利に使うことができそうだ。

実践Common Lisp
作者: Peter Seibel,佐野匡俊,水丸淳,園城雅之,金子祐介
出版社/メーカー: オーム社
発売日: 2008/07/26
メディア: 単行本(ソフトカバー)

LOOPのパーツ(黒帯のためのLOOPより)

LOOPの中では次のようなことができる。

  • 数値的な変数や多様なデータ構造にわたる変数を更新していく
  • ループしている間に見える値を収集(collect)、計数(count)、合計(sum)、最小化(minimize)、最大化(maximize)する
  • 任意のLisp式を実行する
  • いつループを終了するかを決定する
  • それらを条件付きで実行する

上記に加えて、LOOPは以下のようなシンタックスを提供する。

  • ループ内で使用するローカル変数の生成
  • ループの前後に実行する任意のLisp式の指定

サンプル (GNU Emacs 28.2 で動作確認しています)

また、@javacommons さんの以下の記事内の xpand-macro/xpand を用いてマクロ展開結果を取得しています。

今回は…

今回は、LOOP マクロに関する Emacs Lisp と Common Lisp の非互換性について紹介します。

ベクターのリードシンタックスの違い

  • 厳密には、LOOPマクロ自体の違いではないですが…
CLISPの場合
CLISP> (loop for i across #(1 2 3) do (print i))

1
2
3
NIL
ELISPの場合
(cl-loop for i across [1 2 3] do (print i))
    |
    |
    v
(let* ((--cl-vec-- [1 2 3])
       (--cl-idx-- -1)
       (i nil))
  (while (and (setq --cl-idx-- (1+ --cl-idx--))
              (< --cl-idx-- (length --cl-vec--)))
    (setq i (aref --cl-vec-- --cl-idx--))
    (print i))
  nil)


1

2

3
nil

値の累積(accumulation)に関する違い

  • Emacs Lisp では、以下のように concat (文字列の結合) accumulation が使えます。
ELISPのみ
(cl-loop for str in '("A" "B" "C")
         for sep = "" then ","
         concat sep
         concat str)
    |
    |
    v
(let* ((--cl-var--_1 '("A" "B" "C"))
       (str nil)
       (sep nil)
       (--cl-var--_2 "")
       (--cl-var--_3 t))
  (while (consp --cl-var--_1)
    (setq str (car --cl-var--_1))
    (setq sep (if --cl-var--_3 "" ","))
    (setq --cl-var--_2 (concat --cl-var--_2 sep))
    (setq --cl-var--_2 (concat --cl-var--_2 str))
    (setq --cl-var--_1 (cdr --cl-var--_1))
    (setq --cl-var--_3 nil))
  --cl-var--_2)

"A,B,C"

最後に

他にも非互換等ありましたらコメント等でお願いします。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?