2011-07-26 7 views
1

私は、その引数の1つをスロットと文字列で作られた共通のlispで扱いたいと思っています。ここにプロトタイプがあります:スロットと文字列のリストからの値を扱う

(defclass time-info() 
    ((name :initarg name) 
    (calls :initarg calls) 
    (second :initarg second) 
    (consing :initarg consing) 
    (gc-run-time :initarg gc-run-time))) 

(defun print-table (output arg-list time-info-list)()) 

考え方は、その構造を定義するarg-listに基づいてテーブルを出力することです。

(print-table *trace-output* 
      '("|" name "||" calls "|" second "\") 
      my-time-info-list) 

これはトレース出力でasciiで表を印刷します。問題は、明示的にリストの要素をマクロのさまざまな部分で使用する方法をわかりません。

私はこれをどうやって行うのか考えていませんが、私はそれができると確信しています。たぶん、あなたは私を助けることができます:)

+0

なぜそれがマクロではなく機能すべきですか?配列のASCII表現ですか?どちらの配列ですか? –

+0

':initarg'は通常はキーワードであり、あなたのスロットにアクセサまたはリーダーを定義する必要があります。 – Svante

答えて

1

これはformatに基づいています。考え方は、arg-listからフォーマット文字列 を作成することです。

私はそのためのヘルパー関数定義:~がそれらを逃れるためにformat文字列で倍増しなければならないことを

(defun make-format-string-and-args (arg-list) 
    (let ((symbols())) 
    (values (apply #'concatenate 'string 
        (mapcar (lambda (arg) 
          (ctypecase arg 
           (string 
           (cl-ppcre:regex-replace-all "~" arg "~~")) 
           (symbol 
           (push arg symbols) 
           "~a"))) 
          arg-list)) 
      (nreverse symbols)))) 

注意を。

印刷マクロ自体は、ちょうどformatmapcarを生成します。

(defmacro print-table (stream arg-list time-info-list) 
    (let ((time-info (gensym))) 
    (multiple-value-bind (format-string arguments) 
     (make-format-string-and-args arg-list) 
     `(mapcar (lambda (,time-info) 
       (format ,stream ,format-string 
         ,@(mapcar (lambda (arg) 
            (list arg time-info)) 
            arguments))) 
       ,time-info-list))) 

あなたは、このようにそれを呼び出すことができます。

(print-table *trace-output* 
      ("|" name "||" calls "|" second "\\") 
      my-time-info-list) 

をあなたのコードで以下の誤差はご了承下さい

  • あなたはエスケープする必要があります文字列の3210。

  • Secondはすでにcommon-lisp パッケージからエクスポートされた関数名です。あなたは一般的な機能でそれを壊すべきではありません。

+0

ありがとうございました。私は同様の考えに取り組んでいた:) –

0

まず、あなたはおそらく、そこに引用したくないあなたは、マクロを使用している場合(あなたはしかし、機能を使用している場合があり、それをしたいです)。第二に、セパレータと値の間に余白を入れたいですか?第三に、おそらくマクロではなく関数を使うほうが良いでしょう。

"array"と "list"を同じ意味で使用しているようです。彼らはCommon Lispではまったく異なるものです。一般的なシーケンスで動作する操作がありますが、通常、リストに対して繰り返しを行う方法と、配列に対して繰り返し実行する方法があります。

+0

ええ、私はまだマクロで学んでいますが、わかりませんでしたが、あなたが正しいです。見積もりは必要ありません。 –

+0

パディングについては、この例には含まれていなかったオプションにする必要があります。アイデアは、ユーザーには必要でないかもしれないということです。三つ目は、関数とマクロの間に何があるのか​​よく分かりませんでした。私はarrayという言葉を使いました。なぜなら、あなたがそれを印刷するときに得られるものなのですから。私は私のメッセージでこれを編集します:) –

+0

@三人目 - あなたはおそらくあなたがそれを印刷するときにテーブルを手に入れます。 :) – Vatine

1

要件をより正確にする必要があります。マクロと関数は異なるものです。配列とリストも異なっています。

我々はTIME-INFO-LISTを反復する必要があります。だから最初のDOLISTです。

テーブルは、行の説明を有します。説明の各項目は、スロット名または文字列です。そこで、説明を繰り返します。それは第2のDOLISTです。文字列が印刷されます。シンボルはスロット名で、現在のtime-infoインスタンスからスロット値を取得します。

(defun print-table (stream line-format-description time-info-list) 
    (dolist (time-info time-info-list) 
    (terpri stream) 
    (dolist (slot-or-string line-format-description) 
     (princ (etypecase slot-or-string 
       (string slot-or-string) 
       (symbol (slot-value time-info slot-or-string))) 
      stream)))) 

テスト:

> (print-table *standard-output* 
       '("|" name "||" calls "|" second "\\") 
       (list (make-instance 'time-info 
            :name "foo" 
            :calls 100 
            :second 10) 
        (make-instance 'time-info 
            :name "bar" 
            :calls 20 
            :second 20))) 

|foo||100|10\ 
|bar||20|20\ 
関連する問題