🦉

UIOPの勧め。Utility編。

2021/08/05に公開

UIOPの勧め。Utility編。

Introduction.

UIOPとはASDF用のユーティリティライブラリです。

ASDFはシステムビルダのデファクトスタンダードで、処理系にバンドルされてます。
ということはUIOPもバンドルされているわけです。

UIOPは'Already included battery'とみなせます。
本稿ではUIOP/UTILITYが提供している機能の中から、特に筆者が使用頻度が高いと思うものを紹介していきます。

それ、UIOPでできるよ。SPLIT-SEQUENCE編。

UIOP:SPLIT-STRING

SEQUENCEをスプリットする場合、真っ先に候補に上がるライブラリはSPLIT-SEQUENCEです。
ですがスプリットしたいのが文字列である場合ならUIOP:SPLIT-STRINGが使えます。

* (uiop:split-string "foo/bar/bazz" :separator "/")
("foo" "bar" "bazz")

それ、UIOPでできるよ。ALEXANDRIA編。

IF-LET

LETで束縛してからIFで分岐するコードは頻出します。
ネストが深くなるのを防ぐためにはIF-LETが使えます。

* (if-let ((var hoge))
    (then)
    (else))

hogeが非NIL値ならTHEN部が、NILならELSE部が評価されます。

PARSE-BODY

マクロ内で&BODYで受けたフォームをフォーム本体と宣言部に切り分けるのに使います。

(multiple-value-bind (form decls) (uiop:parse-body body)
  ...

APPENDF

変数をAPPENDされたリストで更新します。

* (let ((list '(a)))
    (uiop:appendf list '(b c))
    list)
(A B C)

ENSURE-LIST

引数がリストでなければリストにくくります。
DEFSTRUCTの第一引数のように簡便のためATOMでもよいようにシンタックスが設計されているマクロ引数の正規化に使われます。

* (uiop:ensure-list nil)
NIL

* (uiop:ensure-list :a)
(:A)

EMPTYP

SEQUENCEが空かどうかテストします。

* (uiop:emptyp "")
T

* (uiop:emptyp nil)
T

* (uiop:emptyp #())
T

それ、UIOPでできるよ。CL-UTILITIES編。

WHILE-COLLECTING

リストに値を積み上げるのに使われます。

* (uiop:while-collecting (foo bar)
    (dolist (x '((a 1) (b 2) (c 3)))
      (foo (first x))
      (bar (second x))))
(A B C)
(1 2 3)

ローカル関数で木構造を再帰しながら値を積み上げたい場合や、LOOPマクロで:COLLECTしたいがトップレベルでないのでできない場合などに重宝します。

その他。

NEST

バインド系のコードがネストしてインデントが深くなるのをなんとかしたい場合に使えます。

(uiop:nest
  (let ((var)))
  (flet ((fun ()
           (process))))
  (multiple-value-bind (a b c) (init-fun))
  (with-slots (slot) a
    (do-something ...)))

REMOVE-PLIST-KEYS

PLISTからキーを取り除きます。

* (let ((plist '(:a 1 :b 2 :c 3)))
    (values (uiop:remove-plist-keys '(:a :c) plist)
            plist))
(:B 2)
(:A 1 :B 2 :C 3)

FROB-SUBSTRINGS

unixでsedを繰り返し適用させるような処理を行います。

* (uiop:frob-substrings "foo/bar/bazz"
                        '("bar"))
"foo//bazz"

* (uiop:frob-substrings "foo/bar/bazz"
                        '("bar")
			"hoge")
"foo/hoge/bazz"

* (uiop:frob-substrings "foo/bar/bazzbar"
                        '("bar" "bazz")
			(lambda (match emitter)
			  (cond
			    ((equal match "bar") (funcall emitter "FOO"))
			    ((equal match "bazz") (funcall emitter "hoge")))))
"foo/FOO/hogeFOO"

STRING-PREFIX-P

文字列がPREFIXから始まっているかテストします。

* (uiop:string-prefix-p "pre" "predicate")
T

STRING-SUFFIX-P

文字列がSUFFIXで終わっているかテストします。

* (uiop:string-suffix-p "prepend" "end")
T

LIST-TO-HASH-SET

LISTの要素をキーに持つHASH-TABLEを作って返します。

* (gethash :a (uiop:list-to-hash-set '(:a :b :c)))
T
T

最後に。

使用頻度が高いものを紹介しただけなので他にもまだまだあります。
暇なときにでもソースを眺めておくことを強くおすすめします。

Discussion