(rontolisp) docs
← uiop パッケージ

uiop/utility

uiop/utility は uiop の他のすべてがその上に書かれている層です。文字列、リスト、 プロパティリスト、ハッシュテーブル、タイムスタンプ、コンディションのヘルパで、 オペレーティングシステムを一切必要としません。68 個のエクスポートすべてが実装済み であり、ファイルシステムもサブプロセスもネットワークも触らないため、そのすべてが 4 つのバックエンド — インタプリタ、JVM、2 つの WASM 出力 — で動作します。

どの名前もどちらの綴りからでも到達できます。uiop:strcatuiop/utility:strcat は同じ関数です (uiop パッケージ)。

文字列

関数内容
uiop:strcat文字列指示子を連結します。nil は空文字列、文字は長さ 1 の文字列として扱われます
uiop:reduce/strcatリストに対する strcat:key:start:endreduce と同じ意味です
uiop:string-prefix-p文字列がその接頭辞で始まるか
uiop:string-suffix-p文字列がその接尾辞で終わるか
uiop:string-enclosed-p両方を同時に
uiop:stripln末尾の CR・LF・CRLF を取り除きます。取り除いた後の文字列と取り除いた終端の 2 値を返します
uiop:frob-substrings複数の部分文字列を左から順に置換 (または削除) します。先に一致した範囲の内側は対象になりません
uiop:first-char / uiop:last-char空でない文字列の最初 / 最後の文字。そうでなければ nil
uiop:split-string区切り文字列のいずれかの文字で分割します
uiop:emptypnil および長さ 0 のベクタ・文字列に対して真
uiop:+cr+ / uiop:+lf+ / uiop:+crlf+3 種類の改行を文字列として
uiop:standard-case-symbol-name名前指示子を文字列として。文字列なら大文字化します
uiop:find-standard-case-symbolその名前をパッケージから引きます

strcat の寛容さがこの関数の要点です。省略可能な断片を、条件分岐で包まずに そのまま連結できます。

"abc"
"bbcc"
(T T T)
"hell0 w0rld"

stripln は取り除いたものを第 2 値として返すので、両者を strcat すれば元の行が 復元できます。

("hi" 2)
T

リスト・プロパティリスト・ハッシュテーブル

関数内容
uiop:ensure-listリストでないものを 1 要素のリストで包みます
uiop:length=n-pリストの長さがちょうど n か。n を超えて辿りません
uiop:appendf(appendf place list...)、すなわち (setf place (append place list...))
uiop:remove-plist-key / uiop:remove-plist-keys指定したキーを除いたプロパティリスト — キーワード引数の整理用です
uiop:ensure-gethashエントリを返し、無ければデフォルトを計算して格納します。第 2 値が既に存在したかを示します
uiop:list-to-hash-setリストを equal のハッシュ集合に
uiop:lexicographic< / uiop:lexicographic<=与えた element< で 2 つのリストを要素ごとに比較します
(:A 1)
(1 2 3)
((5 NIL) (5 T))

タイムスタンプ

タイムスタンプは実数または真偽値で、t がマイナス無限大、nil がプラス無限大です。 つまり存在しないファイルは「無限に古く」、不明なファイルは「無限に新しい」— ASDF が ビルド順序を決めるときの考え方です。

関数内容
uiop:timestamp< / uiop:timestamp<=2 つのタイムスタンプを比較します
uiop:timestamps< / uiop:timestamp*<リスト (または引数列) が狭義単調増加か
uiop:earlier-timestamp / uiop:later-timestamp2 つのうち小さい方 / 大きい方
uiop:timestamps-earliest / uiop:timestamps-latestリストに対して
uiop:earliest-timestamp / uiop:latest-timestamp引数列に対して
uiop:latest-timestamp-f(latest-timestamp-f place timestamp...)。場所に累積します
(T T T)
(1 3)
5

timestamps<nil = プラス無限大から比較を始めるため、空でないリストが 「増加している」ことは決してありません — 本家と同じ答えで、直さずにそのままにしてあります。

関数指示子

uiop:ensure-function指示子を関数に変換します。関数はそれ自身、定数 (真偽値・ キーワード・文字・数値・パス名) は (constantly それ)、ハッシュテーブルはその参照関数、 シンボルはその fdefinition、コンスは部分適用された呼び出し (または評価される lambda 形式)、文字列は読み込まれて関数名として評価されます。

関数内容
uiop:ensure-function上記の変換
uiop:call-function(apply (ensure-function spec) args)
uiop:call-functionsリストに対して順に call-function
uiop:access-atアクセサの連鎖を適用します。整数は elt、キーワードは getfnil は恒等、シンボルや関数は呼び出し、コンスは ensure-function です
uiop:access-at-countaccess-at の指定が読む部分オブジェクトの個数
uiop:register-hook-functionフックを変数に push します — 未実装のものを参照
9
3
20

コンディション

名前内容
uiop:not-implemented-errorこの実装が持たない操作を名指しするコンディションと、それをシグナルする関数
uiop:parameter-error操作は存在するが、そのパラメータの組み合わせは受け付けない
uiop:simple-style-warninguiop 自身のスタイル警告 — 本物の style-warning なので標準の型に対するハンドラで捕捉できます
uiop:style-warnフォーマット文字列・コンディション型・コンディションからスタイル警告をシグナルします
uiop:match-condition-pコンディションがパターンに一致するか (型名、#(name package) ベクタ、述語、simple-condition のフォーマット文字列)
uiop:match-any-condition-p複数のパターンのいずれかに
uiop:call-with-muffled-conditions一致するコンディションを抑止してサンクを実行します
uiop:with-muffled-conditionsそのマクロ版
uiop:boolean-to-feature-expression(:and) または (:or) — 常に真 / 常に偽の #+ テスト
uiop:symbol-test-to-feature-expression「このパッケージはこの名前をエクスポートしているか」から同じものを
:MUFFLED
:WARNED
((:AND) (:AND))

知っておくべき差異が 1 つあります。match-condition-p の文字列パターンは simple-condition-format-control と比較されますが、rontolisp ではそこに既に整形済みの メッセージが入っています。したがってフォーマット指示子を含むパターンは一致しません。 指示子を含まないパターンはこれまでどおり一致します。

マクロ

マクロ内容
uiop:if-let束縛したうえで、すべての変数が非 nil のときだけ then 側を選びます
uiop:nest各フォームを直前のフォームの末尾に入れ子にします — インデント対策です
uiop:while-collecting名前ごとに収集関数を束縛します。フォームは各リストを順に多値で返します
uiop:with-upgradability本家は全定義をこれで包みます。ここでは progn です — 下記参照
uiop:with-muffled-conditionscall-with-muffled-conditions の略記
uiop:appendf / uiop:latest-timestamp-f上記の 2 つの define-modify-macro
uiop:compatfmt貧弱な format が読めないプリティプリンタ指示子を除去します。rontolisp はすべて読めるので文字列はそのまま返ります
uiop:uiop-debug開発者個人のデバッグ用ファイルを読み込みます — 未実装のものを参照
uiop:parse-body(マクロではなく関数) 本体をフォーム・宣言・ドキュメント文字列に分解します。マクロを書くライブラリが呼ぶものです
(1 (2 (3)))
((A B) (1 2))
(((+ 1 2)) ((DECLARE (IGNORE X))) "doc")

uiop:with-upgradabilityprogn に展開されます。 本家が自身の定義をすべて これで包むのは、動作中のイメージ内で ASDF が自分自身を再定義できるようにするためです。 本体はコンパイル時・ロード時・実行時に評価され、各関数は notinline と宣言されます。 rontolisp には更新すべきイメージがありません — プログラムは一度コンパイルされて 実行されるだけです — ので、ここではこれが progn の意味そのものです。これは欠落では なく意図的な選択です。定義は書かれたとおりに確立され、コンパイルバックエンドでも トップレベル定義のままです。

(6 5)

文字型は 1 つだけ

本家の文字型の一群が存在するのは、処理系によっては base-charcharacter が 別の型であり、文字列の要素型を調べる必要があるからです。rontolisp の文字型は 1 つだけで — (subtypep 'character 'base-char) は真です — 本家自身の導出を この型格子の上で走らせると、要素は 1 つ、添字は 0、+non-base-chars-exist-p+ は偽に なります。残りはそこから決まります。どの文字列も base 文字列であり、任意の文字列群の 共通要素型は character です。

(0 0 NIL)
(T CHARACTER)

未実装のもの

2 つのメンバは、あるふりをするのではなく rontolisp に無いものを名指しします。 どちらも理由とともに uiop:not-implemented-error をシグナルします。

  • uiop:register-hook-function は実行時に名前で指定された変数に push しますが、 それには (setf (symbol-value var) ...) が必要で、どのバックエンドでもこれは 場所 (place) ではありません。
  • uiop:load-uiop-debug-utility (およびそれを呼ぶ uiop:uiop-debug) は 実行時に計算されたパス名を load しますが、load はどのバックエンドでも コンパイル時の展開です。uiop:*uiop-debug-utility* には本家の既定のフォームが 入ったままです。
$ rontolisp -e '(uiop:register-hook-function (quote *h*) (lambda () 1))'
Unhandled condition: Not (currently) implemented on rontolisp: UIOP/UTILITY:REGISTER-HOOK-FUNCTION pushing onto a hook needs (setf (symbol-value ...)), which is not a place on any backend