1
(defmacro flycheck-define-clike-checker (name command modes)
    `(flycheck-declare-checker ,(intern (format "flycheck-checker-%s" name))
       ,(format "A %s checker using %s" name (car command))
       :command '(,@command source-inplace)
       :error-patterns
       '(("^\\(?1:.*\\):\\(?2:[0-9]+\\):\\(?3:[0-9]+\\): error: \\(?4:.*\\)$"
          error)
         ("^\\(?1:.*\\):\\(?2:[0-9]+\\):\\(?3:[0-9]+\\): warning: \\(?4:.*\\)$"
          warning))
       :modes ',modes))

  (flycheck-define-clike-checker c
                                 ("gcc" "-fsyntax-only" "-Wall" "-Wextra")
                                 c-mode)

上記はhttps://github.com/jedrz/.emacs.d/blob/master/setup-flycheck.elから取得したコードです

https://github.com/lunaryorn/flycheckにある flycheck のチェッカーを定義すること以外には何もしません。

私の問題は些細なことで、すでに 1 日を費やしており、さらに混乱しています。

コードの 2 番目の部分では、定義されたマクロを使用して flycheck を呼び出し、コンパイラを登録します。

(flycheck-define-clike-checker c
                                     ("gcc" "-fsyntax-only" "-Wall" "-Wextra")
                                     c-mode)

上記のコードは完全に機能します。

しかし、コンパイラにいくつかの動的インクルードなどを持たせたかったので、次のように定義された変数があります

(defvar efx-flycheck-c-command '("gcc" "-fsyntax-only" "-Wall" "-Wextra"))

それを次のようなマクロに渡すと

(flycheck-define-clike-checker c
                                         efx-flycheck-c-command
                                         c-mode)

コンパイル エラーが表示される

Debugger entered--Lisp error: (wrong-type-argument sequencep efx-flycheck-c-command)
  append(efx-flycheck-c-command (source-inplace))
  (list (quote quote) (append command (quote (source-inplace))))
  (list (quote flycheck-declare-checker) (intern (format "flycheck-checker-%s" name)) (format "A %s checker" name) (quote :command) (list (quote quote) (app$
  (\` (flycheck-declare-checker (\, (intern (format "flycheck-checker-%s" name))) (\, (format "A %s checker" name)) :command (quote ((\,@ command) source-in$
  (lambda (name command modes) (\` (flycheck-declare-checker (\, (intern (format "flycheck-checker-%s" name))) (\, (format "A %s checker" name)) :command (q$
  (flycheck-define-clike-checker c efx-flycheck-c-command c-mode)
  eval((flycheck-define-clike-checker c efx-flycheck-c-command c-mode) nil)
  eval-last-sexp-1(nil)
  eval-last-sexp(nil)
  call-interactively(eval-last-sexp nil nil)

elisp でマクロがどのように展開されるかについて、私は混乱したと思います。

助けてください!

4

2 に答える 2

2

原則として、実際に使用するのが不便/不可能な場合を除いて、adefunよりもaを使用することをお勧めします。あなたの場合、確かにもっと理にかなっています。唯一の欠点は、引数と引数を引用する必要があることです。defmacrodefundefuncc-mode

于 2013-03-23T16:24:42.330 に答える
1

command引数を評価する評価しないかを決定する必要があります。評価されていない引数を使用すると、変数を引数として渡すことができないという代償を払って、リストをクォートせずに、つまり("gcc" "-Wall")の代わりに型付けできます。'("gcc" "-Wall")評価された引数を使用すると、単純なリストを引用しなければならないという代償を払って、変数 (または実際には任意の式) をマクロに提供できます。

通常、バッククォートでマクロ引数を評価するには、,演算子を使用するだけです。ただし、すでに,@演算子を使用しており、2 回言及commandしているため、次を使用して明示的に評価することをお勧めしevalます。

(defmacro flycheck-define-clike-checker (name command modes)
  (let ((command (eval command)))
    `(flycheck-declare-checker ,(intern (format "flycheck-checker-%s" name))
       ,(format "A %s checker using %s" name (car command))
       :command '(,@command source-inplace)
       :error-patterns
       '(("^\\(?1:.*\\):\\(?2:[0-9]+\\):\\(?3:[0-9]+\\): error: \\(?4:.*\\)$"
          error)
         ("^\\(?1:.*\\):\\(?2:[0-9]+\\):\\(?3:[0-9]+\\): warning: \\(?4:.*\\)$"
          warning))
       :modes ',modes)))

自由に使える の力を利用defmacroして、さらに一歩進んで、マクロがシンボルの場合は評価され、そうでない場合はそのまま使用されるように定義することもできます。これにより、ケーキを食べて食べることができます。つまり、変数名とリテラル リストの両方を渡すことができます。これにより、通常の評価ルールとの一貫性が低下します。リストまたは変数を渡すことはできますが、関数呼び出しなどの任意の式を渡すことはできず、マクロのユーザーを不愉快に驚かせることになります。そのため、実装は読者の演習として残されています。

于 2013-03-23T10:32:35.783 に答える