3

私はときどき Perl 正規表現の夢を見ますが、Common Lisp (CLisp) のフォーマット仕様には、いまだに少し困惑しています。私は次の結果を狙っています:

私が欲しいリスト("No Match" (-2378 11 4) (-2378 11 5))を考えると:

| No Match| -2378 11  4| -2378 11  5|

もう一方の端から。代わりに私が得るものは次のとおりです。

[685]> (fss sd)

("No Match" (-2378 11 4) (-2378 11 5))
[686]> (format t "|~{~9<~a~>~2*~}~:*~{~*~{|~6d~3d~3d~}~}|" (fss sd))
| No Match| -2378 11  4
*** - There are not enough arguments left for this format directive.
      Current point in control string:
        "|~{~9<~a~>~2*~}~:*~{~*~{|~6d~3d~3d~}~}|"
                                           |
The following restarts are available:
ABORT          :R1      Abort main loop
Break 1 [687]> :R1

[688]>

3 分の 2 に到達したことをうれしく思いますが、この状況に少し頭がおかしくなっています。私の理解が正しければ、|~{~9<~a~>~2*~}はリストの最初の要素 を消費しNo Match、残りをスキップします。次の部分は~:*、引数ポインタをリストの先頭にリセットします。次に、~{~}ラッパーは私をリストに入れます。次に、~*リストの既に処理された部分をスキップします。の次のペアは~{~}、引数の最初のサブリストに入ります。最初のサブリストは正しく処理されます。それから...エラー。明らかに、私のフォーマットの理解には何か問題がありますが、それが何であるかは明確ではありません。

CL の残りの部分はかなり単純明快であると感じることがよくありますが、少なくともCL クックブックには「フォーマット クックブック」の章が必要だと本当に思います。

要するに、この志願者は道のより知識のあるフォロワーからの助けを必要としています. ヘルプ!

4

2 に答える 2

4

ソリューションを段階的に構築しました。フォーマット文字列には引数が 1 つしかないため、リストの各要素を出力するフォーマット文字列を作成することから始めました。

CL-USER> (format t "~{|~A~}|"
                 '("No Match" (-2378 11 4) (-2378 11 5)))
|No Match|(-2378 11 4)|(-2378 11 5)|

さて、最初の要素の後、残りのすべての引数を実際に反復処理したいと思います。これは で行うことができます~@{。各要素の周りに角括弧を追加して、反復の境界を確認できるようにしました。

CL-USER> (format t "~{|~A ~@{[~A]~}~}|"
                 '("No Match" (-2378 11 4) (-2378 11 5)))
|No Match [(-2378 11 4)][(-2378 11 5)]|

ここで、フィールド幅がすべて同じではないため、角括弧内のリスト内の各要素を個別に出力する必要があります。イニシャル~A~9<~A~>今に置き換えることもできます。

CL-USER> (format t "~{|~9<~A~>~@{~{|~6d~3d~3d~}~}~}|"
                 '("No Match" (-2378 11 4) (-2378 11 5)))
| No Match| -2378 11  4| -2378 11  5|

現在(これは別の回答でも指摘されています)、~@すぐに続くの使用は、フォーマット文字列を短縮する~{に置き換えることができる構造です。~:@{

CL-USER> (format t "~{|~9<~A~>~:@{|~6d~3d~3d~}~}|"
                 '("No Match" (-2378 11 4) (-2378 11 5)))
| No Match| -2378 11  4| -2378 11  5|

最後に、美的ディレクティブ~Aを使用してフィールド幅を指定できます。 ~mincolAはスペースを右側に~mincol@A置きますが、左側に置くので、 を使用する~<必要はありません。 ~9<~A~>になり~9@Aます:

CL-USER> (format t "~{|~9@A~:@{|~6d~3d~3d~}~}|"
                 '("No Match" (-2378 11 4) (-2378 11 5)))
| No Match| -2378 11  4| -2378 11  5|

この種の漸進的なアプローチは、Lisp で非常に頻繁に使用され、最初に問題の一部を解決してから、漸進的に解決策を改良することができます。書き込み、コンパイル、実行のサイクルがより高価な他の言語とは異なり、Lisp のクイック REPL により、この種のプロセスが非常に簡単になります。

で多くの作業を行う場合は、HyperSpec のformatセクション22.3 Formatted Outputをざっと読む価値があります。ほとんどの機能は、おそらくしばらく使用しないでしょうが、そのセクションにざっと目を通しておけば、必要なときに頭の片隅にあるはずです。(その場合はマニュアルを参照する必要がありますが、過小評価されがちなポイントは、マニュアルに何かがあり、どこを探すべきかを知ることです。)

于 2013-06-16T20:54:48.360 に答える
1

3 番目~{の では、最初のサブリストの要素ごとの印刷に入ります。各反復はサブリストの 3 つの要素を消費するため、1 回のパスの後に実行されます。次に、このループが終了し、次に高いループが次の反復に進みます。外側のリスト (2 番目のサブリスト) の別の要素をスキップしますが、内側のループに再び入るために使用する引数は残っていません。

前後にスキップする代わりに、単に the:@修飾子の両方を使用~{して、残りのリストを処理できます。

"|~{~9<~a~>~:@{|~6d~3d~3d~}~}|"
于 2013-06-16T20:51:29.303 に答える