2

私は Common Lisp を勉強していて、Lisp と Web 開発で遊んでみたいと思っています。私の現在の問題は、含めたいすべてのJavaScriptファイルを反復処理するという単純なアイデアから来ています。私は高速起動のために SBCL と Quicklisp を使用しています。問題は、cl-who使用しているパッケージに関連している可能性があります。

だから私は自分のパッケージを宣言し、次のように始めました:

(defpackage :0xcb0
  (:use :cl :cl-who :hunchentoot :parenscript))
(in-package :0xcb0)

シンプルにするために、問題関数を減らしました。だから私はこのpage機能を持っています:

(defun page (test)
  (with-html-output-to-string
    (*standard-output* nil :prologue nil :indent t)
    (:script
     (:script :type "text/javascript" :href test))))

これにより、目的の出力が生成されます

*(0xcb0::page "foo")

<script>
   <script type='text/javascript' href='foo'></script>
</script>

:scriptこれで、タグを生成するマクロを作成できました。

(defmacro js-source-file (filename)
  `(:script :type "text/javascript" :href ,filename)))

これは期待どおりに機能します。

*(macroexpand-1 '(0XCB0::js-source-file "foo"))

(:SCRIPT :TYPE "text/javascript" :HREF "foo")

pageただし、これを関数に含めると:

(defun page (test)
  (with-html-output-to-string
    (*standard-output* nil :prologue nil :indent t)
    (:script
     (js-source-file "foo"))))

...新しい関数undefined function: :SCRIPTを定義するときに、スタイル警告 ( ) が表示されます。pageまた、page関数を実行すると、次のエラーが発生します。

*(0xcb0::page "foo")

The function :SCRIPT is undefined.
   [Condition of type UNDEFINED-FUNCTION]

埋め込みマクロjs-source-fileは、目的の出力を生成するという点で期待どおりに動作しますが、別の関数内で呼び出されると失敗するのはなぜですか?

PS Lisp でのマクロのトピックは、私のような初心者にとってはかなり疲れる可能性があることを知っています。しかし、現在、これが機能するはずなのに機能しないという事実に頭を悩ませることはできません!

4

2 に答える 2

4

他の良い答えに加えて、特定のケースについて説明しwith-html-outputます。これは、 cl-whoマニュアルの構文とセマンティクスのセクションから派生したものです。

まず、呼び出しを自分でマクロ展開すると、、、、...などのバインディングがwith-html-output確立されていることがわかります. コードを修正するために、次のようにマクロを変更できます。macroletstrhtmftmeschtmwith-html-outputwith-html-output

(defmacro js-source-file (filename)
  `(htm (:script :type "text/javascript" :href ,filename)))

それで:

  1. with-html-outputを含むツリーに展開されます(js-source-file ...)
  2. マクロが展開され、(htm (:script ...))フォームが生成されます。
  3. 次に、マクロレットを展開して内部(with-html-output ...)フォームを生成します。
  4. インナーwith-html-outputは展開加工をしています(:script ...)

ここでマクロを使用するか関数を使用するかを選択する必要があります。通常、関数はインライン化されておらず、実行時に簡単に再定義できます。マクロは理論的には実行時に展開することもできますが、ほとんどの実装 (およびデフォルト構成) では、マクロに依存する関数を再コンパイルする必要があります。マクロに補助関数を呼び出させることもできます。

于 2016-01-30T16:45:42.043 に答える