[parenscript-devel] Conditional nesting of lisp and javascript code

Vladimir Sedach vsedach at gmail.com
Wed Jun 1 19:17:24 UTC 2011


> but, when I do this
>
> (ps:ps (conditional-splice first second 4))
>
> then I get an error
> "The value FIRST is not of type REAL."

Macros get their arguments unevaluated (quoted), so what's going on
inside the macro is:

(<= 'first 'second)

Which is also why (ps:ps (conditional-splice (ps:lisp first) (ps:lisp
second) 4)) doesn't work - you get (<= '(ps:lisp first) '(ps:lisp
second))

You can try doing:

(ps:defpsmacro conditional-splice (cond1 cond2 &body body)
   (when (<= (eval cond1) (eval cond2))
      `(progn , at body)))

This will work because you've already defined first and second with
DEFVAR, and eval picks up on whatever special variables are currently
defined. The problem is it won't work for lexical variables.

In general writing macros like that is a very bad idea because you're
introducing weird constraints on their arguments that have weird
effects on what the macro expands to. That's hard to debug. The
following pattern is better:

(defvar *expand-conditional-splice?* t)

(defpsmacro conditional-splice (&body body)
  (when *expand-conditional-splice?*
    `(progn , at body)))

And then when you need to generate JavaScript:

(let ((*expand-conditional-splice?* (<= first second)))
  (ps:ps* ...code))

Note the ps:ps* there. ps:ps is itself a macro that translates PS code
to JS at macro-expansion (compile) time, but in this example
*expand-conditional-splice?* gets bound at run-time. You can use
ps:ps, but then you have to be careful to set the value of
*expand-conditional-splice?* correctly before your code gets compiled.

This might seem confusing at first, but the key thing is to learn what
happens at compile-time, and what happens at run-time. On Lisp has a
really good introduction to macros and how to think about them:
http://www.paulgraham.com/onlisp.html

Vladimir




More information about the parenscript-devel mailing list