(rontolisp) docs
← マクロ

format

(format destination control-string args...)

Common Lisp の format の最小限のサブセットで、インタプリタと両コンパイラで共有されるマクロとして実装されています。control-string はリテラルでなければなりません。destination が t の場合は princ/prin1/terpri 呼び出しに展開され、標準出力に書き出して nil を返します。destination が nil の場合は整形済み文字列を組み立てて返します(princ-to-string/prin1-to-string 呼び出しに展開され、内部の文字列連結で畳み込まれます)。それ以外の destination 式の場合は同じ方法で文字列を組み立て、1 回の write-string 呼び出しでそのストリーム(with-output-to-string の文字列ストリームまたはファイルストリーム)に書き込み、nil を返します。すべての引数は出力の前に左から右へ評価されます。

Hello world, you are 42!

destination が nil の場合、結果は出力されずに文字列として返されます。

Directives

ディレクティブ意味
~a, ~AAesthetic: 引数を princ のように出力します(文字列は引用符なし)。: を付けると nil は () として出力されます
~s, ~SStandard: 引数を prin1 のように出力します(読み込み可能、文字列は引用符付き)。: を付けると nil は () として出力されます
~d, ~D10進整数。: を付けると桁がカンマで区切られ、@ を付けると非負の値の前に + 記号が付きます
~x, ~o, ~b16進 / 8進 / 2進整数(大文字の桁)。パラメータと修飾子は ~d と同じです
~R基数: ~NR は整数を基数 N(2〜36)で出力します。基数パラメータは必須です(英語の基数詞・序数詞出力は未実装)
~c, ~C文字: write-char のようにグリフを出力します。@ を付けると #\ リーダ構文(prin1 相当)、: を付けると非表示文字は名前(NewlineSpace など)で出力されます
~f, ~F固定小数点形式の浮動小数点数。~,Df は小数点以下 D 桁を出力します(四捨五入)。@ を付けると先頭に + が付きます。完全なパラメータ形式は ~w,d,k,overflowchar,padchar F です
~e, ~E指数(科学的)表記の浮動小数点数: [-]d.ddde[+/-]xx~,De は小数点以下 D 桁を出力します(デフォルト 6、四捨五入)。@ を付けると先頭に + が付きます。完全なパラメータ形式は ~w,d,e,k,overflowchar,padchar,exponentchar E です(k は 1 のみ)
~g, ~G一般浮動小数点形式: 絶対値が [0.1, 1e16)(およびゼロ)の場合は通常の浮動小数点表現、それ以外は ~e 形式で出力します
~$通貨形式: ~D$ は小数点以下 D 桁を出力します(デフォルト 2)。@ を付けると先頭に + が付きます
~%改行(1つ、またはプレフィックスパラメータで指定された数)
~&フレッシュライン: 既に行頭にいない場合のみ改行します
~~リテラルの ~
~(str~)処理済みの str の大文字小文字変換: 小文字化。~:( は各単語の先頭を大文字化、~@( は最初の単語だけ大文字化、~:@( は大文字化します
~[str0~;str1~:;default~]条件選択: 引数(整数)で節を選択します。~:; はデフォルト節を導入します。~N[ / ~#[ はリテラル / 残りの引数の数で選択し、~:[false~;true~] は nil を判定し、~@[str~] は引数が非 nil の場合のみ str を処理します(判定した引数を再利用します)
~{str~}繰り返し: リスト引数の要素に str を繰り返し適用します。~N{ は繰り返し回数を N に制限し、~:{ はサブリストのリストを、~@{ は残りの引数を、~:@{ は残りの各引数をサブリストとして繰り返します
~*引数ジャンプ: ~N*N 個の引数をスキップし(デフォルト 1)、~N:*N 個戻り、~N@* は引数 N へ移動します(デフォルト 0)

ディレクティブはプレフィックスパラメータ(~ の後にカンマ区切りで記述)と :/@ 修飾子を受け付けます。パラメータは10進数、文字('c)、v(引数を1つ消費してその値を使う)、または #(残りの引数の数)のいずれかです。フィールドディレクティブ(~a/~s/~d/~x/~o/~b/~f/~e/~$)は先頭に最小幅パラメータを取ります。幅より短いテキストはパディングされます(パッド文字パラメータで指定 -- 'c リテラルまたは実行時の v -- デフォルトは空白)。~a/~s は右側をパディングします(@ を付けると左側)。数値は左側をパディングします。

Hello world, you are 42 years old.
1,000,000 and +42
3.14 and 3.14
1.2345e+3 and 3.1416e+0
foo       |00042|
Hello world!
FF 100 101 10000
a #\b Newline
foo bar Foo Bar
one yes x=42
<1><2> (x,1)(y,2) a b
1  1

Limitations

その他の出力先(ストリーム、フィルポインタ付き文字列)はサポートされておらず、制御文字列を実行時の値にすることはできず、カラム制御ディレクティブ(~t~<...~>)、ループ脱出の ~^、基数パラメータのない ~r は実装されていません。さらに以下の点に注意してください。

  • 桁数指定のない ~f(および ~g の固定小数点側)は各バックエンドのネイティブな浮動小数点出力にフォールバックするため、正確な形式はバックエンド依存です。可搬性のある出力には桁数を指定してください。~g はプレフィックスパラメータを受け付けません。
  • ~e は仮数部を整数演算から組み立てるため(どのバックエンドでも出力は同一になります)、桁数はリテラルでなければならず、実行時の v は使えません。WASM バックエンドは整数を i31 の範囲に制限するため、スケーリングされた仮数部により ~,De の精度はおよそ D ≤ 8 桁に制限されます。デフォルト(~e、6桁)はその範囲に十分収まります。~e のスケールファクターは 1(デフォルト)のみで、~f/~e のオーバーフロー文字にはリテラルの幅指定が必要です。
  • ~%/~&/~~ の繰り返し回数はリテラルまたは # でなければなりません(そこでは実行時の v 回数はサポートされません)。~& は destination が t の場合は実際の出力カラムから改行を出すかどうかを判断しますが、destination が nil の場合と複合ディレクティブ(~(/~[/~{)の本体内では周囲のリテラルテキスト(静的な近似)から判断します。
  • format は静的に展開されるため、実行時に節を選択する ~[ ではすべての節が同じ数の引数を消費する必要があり(リテラルまたは # セレクタならこの制限はありません)、~@[ の節は判定した引数だけをちょうど消費しなければならず、~{ ... ~} の本体内では #~@{ は使えません。
  • WASM バックエンドでは整数が i31 の範囲に制限されるため、非常に大きい(多倍長)整数の ~:d による桁区切り(およびそのような値の ~x/~o/~b/~r)はインタプリタと JVM バックエンドでのみ動作します。

他のマクロと同様に、format はコンパイル出力に埋め込まれた eval ランタイムでは認識されません(コンパイルされた eval の制限を参照)。