5

私はPractical Common Lispに取り組んできましたが、演習として、数値が別の数値の倍数であるかどうかを判断するマクロを作成することにしました。

(defmacro multp (value factor)
`(= (rem ,value ,factor) 0))

そのため、: (multp 40 10) は true と評価されますが、そうで はあり(multp 40 13) ません

問題は、このマクロが何らかの方法でリークするかどうかです。また、これは「良い」Lispですか?使用できる既存の関数/マクロは既にありますか?

4

4 に答える 4

11

Siebel は、リークの可能性のあるソースの広範な概要を (とにかく単純なケースについて) 提供しますが、ここにはそれらのいずれもありません。valueとはどちらもfactor一度だけ順番に評価され、rem副作用はありません。

ただし、これは良い Lisp ではありません。この場合、マクロを使用する理由がないからです。機能

(defun multp (value factor)
  (zerop (rem value factor)))

は、すべての実用的な目的で同一です。( の使用に注意してくださいzerop。この場合、物事がより明確になると思いますが、強調する必要がある場合、テストしている値がゼロ以外の場合でも意味がある可能性があることを強調する必要がある場合は、(= ... 0)より良いかもしれません)

于 2008-09-13T02:21:26.400 に答える
2

あなたのマクロは私にはうまく見えます。リーキー マクロが何かはわかりませんが、あなたのマクロは非常に単純で、gensym を必要としません。これが「良い」Lisp である限り、私の経験則では、関数が機能しない場合にのみマクロを使用します。この場合、マクロの代わりに関数を使用できます。ただし、このソリューションが機能する場合は、使用しない理由はありません。

于 2008-09-13T02:21:44.840 に答える
1

原則として、ユーザーはこれを行うことができます。

(flet ((= (&rest args) nil))
  (multp 40 10))

これは NIL と評価されます... ただし、ANSI CL では、CL:= を含むほとんどの標準シンボルを再バインドすることは違法であるため、この特定のケースでは安全です。

もちろん、一般的には、参照の非透過性 (マクロが展開されるコンテキストから識別子を取得すること) とマクロの不衛生 (展開されたコードに識別子を漏らすこと) の両方に注意する必要があります。

于 2008-09-17T10:28:16.570 に答える
0

いいえ、マクロの「レキシカル クロージャ」で導入されたシンボルは外部に解放されません。

ほとんどの場合、偶発的な漏れは悪いことですが、漏れは必ずしも悪いことではないことに注意してください。私が取り組んだあるプロジェクトでは、次のようなマクロが役立つことがわかりました。

(defmacro ana-and (&rest forms)
  (loop for form in (reverse forms)
        for completion = form then `(let ((it ,form))
                                      (when it
                                       ,completion))
        finally (return completion)))

これにより、シーケンス内の以前の呼び出しから引き渡された引数 (および NIL を返すことによって通知される失敗) を使用して、シーケンスで実行する必要があることを「短絡」することができました。このコードが由来する特定のコンテキストは、パーサー ジェネレーターを使用して適切なパーサーを作成することは、手でローリングするよりも多くの作業を必要とする、十分にまとまった構文を持つ構成ファイル用の手書きのパーサー用です。

于 2008-11-06T11:57:48.930 に答える