Search code examples
lispcommon-lispparenscript

Using parenscript set-interval function


I've seen many examples where the (set-interval "my-method" n) function is used to call a function every n seconds in the browser, but I cannot get the set-interval function to run.

If I use:

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

I get a lot of namespace collisions and set-interval is still an undefined function.

I've also tried (ps:unobfuscate-package "ps-window-wd-symbols") which returns NIL and does nothing.

What is the correct way of doing this?

Update: using (apropos "set-interval") provides:

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

So it's being provided in two places. Trying (smackjack::set-interval NIL NIL) also causes an Undefined function error.

Using M-. returns "No known Symbol" in my main project namespace.


Solution

  • The best way to use this functions is using it inside de defmacro ps.

    As showing in the doc comments in code you can find this:

    ;; 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.

    and the set-interval function is exported by ps-window-wd-symbols package and not with parenscript package

    the 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.

    take a look at 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))))))))