使用 parenscript 设置间隔函数

Using parenscript set-interval function

我看过很多例子,在浏览器中使用(set-interval "my-method" n)函数每n秒调用一个函数,但是我无法将set-interval函数获取到运行。

如果我使用:

(ql:quickload :parenscript)
(use-package :parenscript)
(use-package: ps-window-wd-symbols)

我遇到了很多命名空间冲突,set-interval 仍然是一个未定义的函数。

我也试过 (ps:unobfuscate-package "ps-window-wd-symbols") returns NIL 并且什么都不做。

正确的做法是什么?

更新:使用 (apropos "set-interval") 提供:

(apropos "set-interval")
                     SET-INTERVAL
          SMACKJACK::SET-INTERVAL
PS-WINDOW-WD-SYMBOLS:SET-INTERVAL

所以它在两个地方提供。尝试 (smackjack::set-interval NIL NIL) 也会导致未定义的函数错误。

在我的主项目命名空间中使用 M-. returns "No known Symbol"。

AFAIK,set-interval 只是一个符号而不是实际函数(在 Lisp 中)。 Parenscript 生成 Javascript 代码,然后可以在 JS 解释器(例如浏览器)中 运行 ,但这不是解释器本身。

Parenscript 提供了一种混淆符号的方法,但也可以保证某些符号不被混淆。 The documentation 说:

Since Parenscript doesn't know anything about the DOM or other JavaScript libraries, library function and property names might be inadvertently obfuscated. To help prevent that, Parenscript comes with the ps-dom1-symbols, ps-dom2-symbols, ps-window-wd-symbols, ps-dom-nonstandard-symbols and ps-dhtml-symbols symbol packages that define various DOM property and function identifiers as exported symbols (in both case-sensitive and insensitive variants), which you can import into your packages to help prevent symbols like pageXOffset from being obfuscated. The ps-dhtml-symbols package contains the broadest range of symbols and is most generally useful.

If you use obfuscation and external JavaScript libraries, you can use the same technique to define your own packages with symbols that will not be obfuscated.

Smackjack 也会生成对 setInterval (pusher.lisp:189) 的调用,但它不会从上述包中导入符号。这不是真正的问题,因为这里只使用了符号的名称,并且没有进行任何混淆。换句话说,smackjack::set-intervalps-window-wd-symbols:set-interval 都映射到相同的 Javascript 函数。

使用此函数的最佳方法是在 defmacro ps.

中使用它

如代码中的文档注释所示,您可以找到:

;; These are convenience packages that export JS and browser DOM ;; symbols. If you :use the packages in a package FOO and then ;; obfuscate FOO, it will prevent the JS symbols from getting ;; mangled.

;; For most web development tasks, you want to import PS-JS-SYMBOLS, ;; PS-WINDOW-WD-SYMBOLS (which includes DOM level 2 and the w3c Window ;; working draft), and possibly the PS-DOM-NONSTANDARD-SYMBOLS.

并且设置间隔函数由 ps-window-wd-symbols 包而不是 parenscript 包导出

defmacro ps:

"Given Parenscript forms (an implicit progn), compiles those forms to a JavaScript string at macro-expansion time. Expands into a form which evaluates to a string.

看看the following gist:

    (ql:quickload :parenscript)
(ql:quickload :cl-who)
(ql:quickload :clack)
(in-package :ps)
(defvar *canvas-id* "alien-canvas")
(clack:clackup
 (lambda (env)
   (list 200
         '(:content-type "text/html")
         (list
          (who:with-html-output-to-string (*standard-output* nil :prologue t :indent t)
            (:html
             (:head
              (:script  :type "text/javascript"
               (who:fmt "~A"
                        (ps (defvar x 0)
                            (defvar y 0)
                            (defvar dx 1)
                            (defvar dy 1)
                            (defvar img (new -image))
                            (setf (@ img src) "http://www.lisperati.com/lisplogo_alien_128.png")
                            (set-interval "draw()" 5)

                            (defun draw ()
                              (let ((w 128)
                                    (h 75)
                                    (canvas ((@ document get-element-by-id) #.*canvas-id*)))
                                (if (or (not canvas) (not (@ canvas get-context)))
                                    (return false))
                                (let ((ctx ((@ canvas get-context) "2d")))
                                  ((@ ctx fill-rect) 0 0 500 500)
                                  (if (and (<= (+ x dx w) 500) (<= 0 (+ x dx)))
                                      (setf x (+ x dx))
                                      (setf dx (* dx -1)))
                                  (if (and (<= (+ y dy h) 500) (<= 0 (+ y dy)))
                                      (setf y (+ y dy))
                                      (setf dy (* dy -1)))
                                  ((@ ctx draw-image) img x y))))))))
             (:body (:canvas :id *canvas-id* :width 500 :height 500))))))))