4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=utf-8">
6 <title>Parenscript Reference Manual
</title>
8 <style type=
"text/css">
26 <center><h1>Parenscript Reference Manual
</h1></center>
28 <h2>Table of Contents
</h2>
31 <li><a href=
"#section-ps-compiler">The Parenscript compiler
</a></li>
32 <li><a href=
"#section-symbolconv">Symbol conversion
</a></li>
33 <li><a href=
"#section-namespace">The Parenscript namespace system
</a>
35 <li><a href=
"#section-obfuscation">Identifier obfuscation
</a></li>
36 <li><a href=
"#section-minification">Minification
</a></li>
39 <li><a href=
"#reserved-symbols">Reserved symbols
</a></li>
40 <li><a href=
"#section-statements-expressions">Statements, expressions, and return
</a></li>
41 <li><a href=
"#section-types">Types and type predicates
</a></li>
42 <li><a href=
"#section-literals">Literals
</a>
44 <li><a href=
"#ssection-numbers">Numbers
</a></li>
45 <li><a href=
"#ssection-strings-chars">Strings and characters
</a></li>
46 <li><a href=
"#ssection-regex">Regular expressions
</a></li>
47 <li><a href=
"#ssection-booleans">Booleans and undefined
</a></li>
50 <li><a href=
"#section-objects">Objects
</a></li>
51 <li><a href=
"#section-arrays">Arrays
</a></li>
52 <li><a href=
"#section-arithmetic">Arithmetic and boolean operators
</a></li>
53 <li><a href=
"#section-math">Mathematical functions and constants
</a></li>
54 <li><a href=
"#section-blocks">Blocks
</a></li>
55 <li><a href=
"#section-functions">Functions and multiple values
</a></li>
56 <li><a href=
"#section-control-transfer">Control transfer and exceptions
</a></li>
57 <li><a href=
"#section-conditionals">Conditionals
</a></li>
58 <li><a href=
"#section-variables">Variable binding and declaration
</a></li>
59 <li><a href=
"#section-assignment">Assignment
</a></li>
60 <li><a href=
"#section-iteration">Iteration
</a></li>
61 <li><a href=
"#section-macros">Macros
</a>
63 <li><a href=
"#ssection-defining-macros">Defining macros
</a></li>
64 <li><a href=
"#ssection-symbol-macros">Symbol macros
</a></li>
65 <li><a href=
"#ssection-gensym">Gensym
</a></li>
68 <li><a href=
"#section-utilities">Utilities
</a>
70 <li><a href=
"#ssection-dom">DOM
</a></li>
71 <li><a href=
"#ssection-html-gen">HTML generation
</a></li>
74 <li><a href=
"#section-runtime-library">Runtime library
</a></li>
75 <li><a href=
"#section-slime-integration">SLIME integration
</a></li>
78 <h2 id=
"section-ps-compiler">The Parenscript compiler
</h2>
80 <li>(
<code id=
"ps">PS
</code> &body body)
</li>
81 <li>(
<code id=
"ps-to-stream">PS-TO-STREAM
</code> stream &body body)
</li>
82 <li>(
<code id=
"ps*">PS*
</code> &rest body)
</li>
83 <li>(
<code id=
"ps-doc">PS-DOC
</code> &body body)
</li>
84 <li>(
<code id=
"ps-doc*">PS-DOC*
</code> &body body)
</li>
85 <li>(
<code id=
"ps-inline">PS-INLINE
</code> form &optional
<code>*JS-STRING-DELIMITER*
</code>)
</li>
86 <li>(
<code id=
"ps-inline*">PS-INLINE*
</code> form &optional
<code>*JS-STRING-DELIMITER*
</code>)
</li>
87 <li>(
<code id=
"ps-compile-stream">PS-COMPILE-STREAM
</code> stream)
</li>
88 <li>(
<code id=
"ps-compile-file">PS-COMPILE-FILE
</code> file)
</li>
89 <li>(
<code id=
"lisp">LISP
</code> lisp-forms)
</li>
90 <li>(
<code id=
"symbol-to-js-string">SYMBOL-TO-JS-STRING
</code> symbol)
</li>
92 <li><code id=
"*js-target-version*">*JS-TARGET-VERSION*
</code></li>
93 <li><code id=
"*parenscript-stream*">*PARENSCRIPT-STREAM*
</code></li>
94 <li><code id=
"*js-string-delimiter*">*JS-STRING-DELIMITER*
</code></li>
95 <li><code id=
"*js-inline-string-delimiter*">*JS-INLINE-STRING-DELIMITER*
</code></li>
96 <li><code id=
"*ps-read-function*">*PS-READ-FUNCTION*
</code></li>
97 <li><code id=
"*version*">*VERSION*
</code></li>
98 <li><code id=
"*defined-operators*">*DEFINED-OPERATORS*
</code></li>
102 <dt>body
</dt> <dd>implicit
<code>PROGN
</code></dd>
105 <p>The difference between the regular and
<code>*
</code> versions
106 of the Parenscript compiler forms is roughly the difference
107 between
<code>COMPILE
</code>
108 and
<code>EVAL
</code>. The
<code>*
</code> forms are functions
109 that do all compilation when they are evaluated, while the
110 regular forms are macros that do almost all (except for the use
111 of the
<code>LISP
</code> special form, see below) compilation at
112 macro-expansion time.
</p>
114 <p><code>PS
</code> and
<code>PS*
</code> are the main interfaces to
115 the Parenscript compiler. They come with
<code>PS-DOC
</code>
116 and
<code>PS-DOC*
</code> counterparts which compile the given
118 with
<a href=
"#*ps-gensym-counter*"><code>*PS-GENSYM-COUNTER*
</code></a>
119 bound to
0, and are useful for writing automated tests.
</p>
121 <p>By default, Parenscript writes output to a string. You can
122 output directly to a stream in one of two ways: either by
123 using
<code>PS-TO-STREAM
</code> instead of
<code>PS
</code>, or by
124 binding
<code>*PARENSCRIPT-STREAM*
</code> before
125 calling
<code>PS*
</code>.
</p>
127 <p><code>PS-INLINE
</code> and
<code>PS-INLINE*
</code> take a single
128 Parenscript form and output a string starting
129 with
<code>javascript:
</code> that can be used in HTML node
130 attributes. As well, they provide an argument to bind the value of
131 <code>*JS-STRING-DELIMITER*
</code> to control the value of the
132 JavaScript string escape character to be compatible with
133 whatever the HTML generation mechanism is used (for example, if
134 HTML strings are delimited using
<code>#\'
</code>,
135 using
<code>#\
"</code> will avoid conflicts without
136 requiring the output JavaScript code to be escaped). By default
138 from
<code>*JS-INLINE-STRING-DELIMITER*
</code>.
</p>
140 <p>Parenscript code can be compiled from a stream or file
141 via
<code>PS-COMPILE-STREAM
</code>
142 and
<code>PS-COMPILE-FILE
</code>, respectively. The special
143 variable
<code>*PS-READ-FUNCTION*
</code> is bound to the function
144 used to read the forms from the file/stream (
<code>READ
</code> by
145 default), and can be used to provide completely customizable
146 syntax for Parenscript files.
</p>
148 <p>Parenscript can also call out to arbitrary Common Lisp code at
149 <i>output time
</i> (that is, every time an expression containing
150 a call to the Parenscript compiler is evaluated, compared
151 to
<i>compile time
</i>, where the effect is accomplished using
152 macros) using the special form
<code>LISP
</code>. The form
153 provided to
<code>LISP
</code> is evaluated, and its result is
154 compiled as though it were Parenscript code. For
<code>PS
</code>
155 and
<code>PS-INLINE
</code>, the Parenscript output code is
156 generated at macro-expansion time, and the
<code>LISP
</code>
157 statements are inserted inline into the output and have access
158 to the enclosing Common Lisp lexical
159 environment.
<code>PS*
</code> and
<code>PS1*
</code> evaluate the
160 <code>LISP
</code> forms using
<code>EVAL
</code>, providing them
161 access to the current dynamic environment only (of course,
162 using
<code>LISP
</code> when calling the
<code>*
</code> forms is
163 not strictly necessary, as the values can be inserted inline
166 <p><code>*JS-TARGET-VERSION*
</code> (
<code>1.3</code> by default)
167 controls which version of JavaScript that Parenscript
168 targets. For newer versions of JS, some Parenscript special
169 forms may compile to more concise and/or efficient expressions
170 that are not present in earlier versions of JavaScript.
</p>
172 <p><code>SYMBOL-TO-JS-STRING
</code> is the Parenscript function
173 responsible for translating Common Lisp symbols to JavaScript
174 identifiers (see the section
175 on
<a href=
"#section-symbolconv">symbol conversion
</a> for the
176 translation rules). It is helpful for writing libraries or other
177 pieces of code that will interface with Parenscript-generated
180 <p>Newer versions of Parenscript may implement Common Lisp special
181 forms, functions or macros that were left unimplemented by earlier
182 versions. This can cause problems if your code provides
183 implementations for those forms itself. To help deal with
184 this,
<code>*DEFINED-OPERATORS*
</code> provides a list of special
185 forms, macros, and symbol macros defined by Parenscript
186 itself.
<code>*VERSION*
</code> is bound to the current release
187 version number of Parenscript.
</p>
189 <h2 id=
"section-symbolconv">Symbol conversion
</h2>
191 <p>Parenscript supports output for both case-sensitive and
192 case-insensitive symbols. By default the Lisp reader upcases all
193 symbols. By setting readtable-case
194 to
<a href=
"http://www.lispworks.com/documentation/lw50/CLHS/Body/23_ab.htm">:invert
</a>
196 the
<a href=
"http://common-lisp.net/project/named-readtables/">named-readtables
</a>
197 library to make this more convenient) symbol case is preserved,
198 and Parenscript will output mixed-case symbols
199 (like
<code>encodeURIComponent
</code>) correctly.
</p>
201 <p>Lisp symbols (other than keywords) that are all uppercase or
202 contain special characters are converted to JavaScript
203 identifiers by following a few simple rules. Special
204 characters
<code>!, ?, #, @, %, /, *
</code> and
<code>+
</code>
205 get replaced by their written-out equivalents
"bang",
"what",
206 "hash",
"at",
"percent",
"slash",
"start" and
"plus"
207 respectively. The
<code>$
</code> character is untouched.
</p>
210 <dt><code>!?#@%
</code></dt>
211 <dd><code>bangwhathashatpercent;
</code></dd>
214 <p>The
<code>-
</code> is an indication that the following
215 character should be converted to uppercase.
</p>
218 <dt><code>bla-foo-bar
</code></dt>
219 <dd><code>blaFooBar;
</code></dd>
222 <p>JavaScript identifiers that begin with an uppercase letter can
223 be obtained with a leading
<code>-
</code> or
<code>*
</code>.
</p>
226 <dt><code>*array
</code></dt>
227 <dd><code>Array;
</code></dd>
230 <p>A symbol starting and ending with
<code>+
</code>
231 or
<code>*
</code> is converted to all uppercase, to signify that
232 this is a constant or a global variable.
</p>
235 <dt><code>*global-array*
</code></dt>
236 <dd><code>GLOBALARRAY;
</code></dd>
239 <p>Keywords are not translated to JavaScript identifiers, but are
240 printed in lower case without any character substitution as
241 strings. This is done because strings are the closest equivalent
242 to Common Lisp keywords (being self-evaluating objects in
243 JavaScript), and to permit keywords to be used for identifying
244 various symbols (for example, as tokens in a parser).
</p>
247 <dt><code>:+
</code></dt>
248 <dd><code>'+';
</code></dd>
250 <dt><code>:foo-Bar
</code></dt>
251 <dd><code>'foo-bar';
</code></dd>
254 <h2 id=
"section-namespace">The Parenscript namespace system
</h2>
256 <li>(
<code id=
"in-package">in-package
</code> package-designator)
</li>
257 <li>(
<code id=
"use-package">use-package
</code> package-designator)
</li>
258 <li>(setf (
<code id=
"ps-package-prefix">PS-PACKAGE-PREFIX
</code> package-designator) string)
</li>
261 <p>Although JavaScript does not offer namespacing or a package system,
262 Parenscript does provide a namespace mechanism for generated
263 JavaScript by integrating with the Common Lisp package system. Since
264 Parenscript code is normally read in by the Lisp reader, all symbols
265 (except for uninterned ones, ie - those specified with
266 the
<code>#:
</code> reader macro) have a Lisp package. By default, no
267 packages are prefixed. You can specify that symbols in a particular
268 package receive a prefix when translated to JavaScript with the
269 <code>PS-PACKAGE-PREFIX
</code> place.
</p>
272 <pre>(defpackage
"PS-REF.MY-LIBRARY"
273 (:use
"PARENSCRIPT"))
274 (setf (ps-package-prefix
"PS-REF.MY-LIBRARY")
"my_library_")
</pre>
279 <pre>(defun ps-ref.my-library::library-function (x y)
280 (return (+ x y)))
</pre>
284 <pre>function my_library_libraryFunction(x, y) {
291 <p>Parenscript provides
<code>IN-PACKAGE
</code>
292 and
<code>USE-PACKAGE
</code> special forms, primarily useful
293 with
<a href=
"#ps-compile-file"><code>PS-COMPILE-FILE
</code></a>
294 and
<a href=
"#ps-compile-stream"><code>PS-COMPILE-STREAM
</code></a>.
</p>
296 <h3 id=
"section-obfuscation">Identifier obfuscation
</h3>
298 <li>(
<code id=
"obfuscate-package">OBFUSCATE-PACKAGE
</code> package-designator &optional symbol-map)
</li>
299 <li>(
<code id=
"unobfuscate-package">UNOBFUSCATE-PACKAGE
</code> package-designator)
</li>
302 <p>Similar to the namespace mechanism, Parenscript provides a
303 facility to generate obfuscated identifiers in specified CL
304 packages. The function
<code>OBFUSCATE-PACKAGE
</code> may
305 optionally be passed a closure that maps symbols to their
306 obfuscated counterparts. By default, the mapping is done
307 using
<code><a href=
"#ps-gensym">PS-GENSYM
</a></code>.
</p>
310 <pre>(defpackage
"PS-REF.OBFUSCATE-ME")
311 (obfuscate-package
"PS-REF.OBFUSCATE-ME"
312 (let ((code-pt-counter #x8CF6)
313 (symbol-map (make-hash-table)))
315 (or (gethash symbol symbol-map)
316 (setf (gethash symbol symbol-map)
317 (make-symbol (string (code-char (incf code-pt-counter)))))))))
</pre>
322 <pre>(defun ps-ref.obfuscate-me::a-function (a b ps-ref.obfuscate-me::foo)
323 (+ a (ps-ref.my-library::library-function b ps-ref.obfuscate-me::foo)))
</pre>
327 <pre>function 賷(a, b, 賸) {
328 return a + libraryFunction(b, 賸);
334 <p>The obfuscation and namespace facilities can be used on packages
335 at the same time.
</p>
337 <p>Since Parenscript doesn't know anything about the DOM or other
338 JavaScript libraries, library function and property names might be
339 inadvertently obfuscated. To help prevent that, Parenscript comes
341 the
<code>ps-dom1-symbols
</code>,
<code>ps-dom2-symbols
</code>,
<code>ps-window-wd-symbols
</code>,
<code>ps-dom-nonstandard-symbols
</code>
342 and
<code>ps-dhtml-symbols
</code> symbol packages that define
343 various DOM property and function identifiers as exported symbols
344 (in both case-sensitive and insensitive variants), which you can
345 import into your packages to help prevent symbols
346 like
<code>pageXOffset
</code> from being
347 obfuscated. The
<code>ps-dhtml-symbols
</code> package contains the
348 broadest range of symbols and is most generally useful.
</p>
350 <p>If you use obfuscation and external JavaScript libraries, you
351 can use the same technique to define your own packages with
352 symbols that will not be obfuscated.
</p>
354 <h3 id=
"section-minification">Minification
</h3>
356 <li><code id=
"*ps-print-pretty*">*PS-PRINT-PRETTY*
</code></li>
357 <li><code id=
"*indent-num-spaces*">*INDENT-NUM-SPACES*
</code></li>
360 <p><code>*PS-PRINT-PRETTY*
</code>
361 and
<code>*INDENT-NUM-SPACES*
</code> control whether the resulting
362 JavaScript code is pretty-printed, and if so, how many spaces go
363 into each indent level, respectively. By default the code is
364 pretty-printed with
4 spaces per indent level.
</p>
366 <p>Setting
<code>*PS-PRINT-PRETTY*
</code> to nil and turning
367 on
<a href=
"#section-obfuscation">obfuscation
</a> will minify the
368 generated JavaScript code.
</p>
370 <h2 id=
"reserved-symbols">Reserved symbols
</h2>
372 <p>The following symbols are reserved in Parenscript, and should not
373 be used as variable names.
</p>
376 ! ~ ++ -- * / % + -
<< >> >>> < >
377 <=
>= == != === !== & ^ | && || *= /= %= += -=
<<=
378 >>=
>>>= &= ^= |=
1-
1+ @ ABSTRACT AND AREF ARRAY
379 BOOLEAN BREAK BYTE CASE CATCH CHAR CLASS COMMA CONST CONTINUE
380 CREATE DEBUGGER DECF DEFAULT DEFUN DEFVAR DELETE DO DO* DOEACH
381 DOLIST DOTIMES DOUBLE ELSE ENUM EQL EXPORT EXTENDS F FALSE FINAL
382 FINALLY FLOAT FLOOR FOR FOR-IN FUNCTION GOTO IF IMPLEMENTS
383 IMPORT IN INCF INSTANCEOF INT INTERFACE JS LABELED-FOR LAMBDA
384 LET LET* LISP LIST LONG MAKE-ARRAY NATIVE NEW NIL NOT OR PACKAGE
385 PRIVATE PROGN PROTECTED PUBLIC RANDOM REGEX RETURN SETF SHORT
386 GETPROP STATIC SUPER SWITCH SYMBOL-MACROLET SYNCHRONIZED T THIS
387 THROW THROWS TRANSIENT TRY TYPEOF UNDEFINED UNLESS VAR VOID
388 VOLATILE WHEN WHILE WITH WITH-SLOTS
391 <h2 id=
"section-statements-expressions">Statements, expressions, and return
</h2>
393 <p>In contrast to Lisp, where everything is an expression,
394 JavaScript makes an arbitrary distinction between expressions,
395 which yield a value and can be nested in other expressions, and
396 statements, which have no value and cannot occur in
399 <p>Some Parenscript special forms compile to expressions, while
400 others can only compile to statements. Certain Parenscript
401 forms, like
<code>IF
</code> and
<code>PROGN
</code>, generate
402 different JavaScript depending on if they are used in an
403 expression context or a statement context. In such cases,
404 Parenscript tries to generate statement code if possible to
405 increase readability, only falling back to the expression code
406 if it is necessary.
</p>
408 <dl><dt><code>(+ i (if x (foo) (bar)))
</code></dt>
409 <dd><code>i + (x ? foo() : bar());
</code></dd>
411 <dt><code>(if x (foo) (bar))
</code></dt>
422 <p>One important feature found in Lisp but absent in JavaScript is
423 implicit return in functions. Parenscript supports implicit
424 return by having a
<code>RETURN
</code> special form that works
425 around the statement-expression dichotomy:
</p>
434 <pre>function foo(x) {
443 (
1 (loop repeat
3 do (alert
"foo")))
445 (otherwise
4)))
</pre>
452 for (var _js1 =
0; _js1 <
3; _js1 +=
1) {
466 <p>Note that Parenscript does not enforce the statement-expression
467 dichotomy, so it is possible to generate syntactically incorrect
468 JavaScript by nesting special forms that only compile to
469 statements in a context that calls for an expression:
</p>
472 <dt><code>(+
1 (dotimes (x
3) (+ x x)))
</code></dt>
475 <pre>1 + for (var x =
0; x <
3; x +=
1) {
482 <h2 id=
"section-types">Types and type predicates
</h2>
484 <li>(
<code id=
"typeof">TYPEOF
</code> object)
</li>
485 <li>(
<code id=
"instanceof">INSTANCEOF
</code> object type)
</li>
486 <li>(
<code id=
"null">NULL
</code> object)
</li>
487 <li>(
<code id=
"undefined">UNDEFINED
</code> object)
</li>
488 <li>(
<code id=
"defined">DEFINED
</code> object)
</li>
489 <li>(
<code id=
"stringp">STRINGP
</code> object)
</li>
490 <li>(
<code id=
"numberp">NUMBERP
</code> object)
</li>
491 <li>(
<code id=
"functionp">FUNCTIONP
</code> object)
</li>
492 <li>(
<code id=
"objectp">OBJECTP
</code> object)
</li>
496 <dt>object
</dt> <dd>an expression yielding an object
</dd>
497 <dt>type
</dt> <dd>a type designator
</dd>
500 <p>Parenscript is based around the JavaScript type system, and
501 does not introduce any new types or objects, nor does it attempt
502 to provide a Common Lisp-like interface to the type system.
</p>
504 <h2 id=
"section-literals">Literals
</h2>
506 <h3 id=
"ssection-numbers">Numbers
</h3>
508 <p>Parenscript prints all integer literals as integers, and floats
509 and rationals as floats, in base
10.
</p>
512 <dt><code>1</code></dt>
513 <dd><code>1;
</code></dd>
515 <dt><code>123.123</code></dt>
516 <dd><code>123.123;
</code></dd>
518 <dt><code>3/
4</code></dt>
519 <dd><code>0.75;
</code></dd>
521 <dt><code>#x10
</code></dt>
522 <dd><code>16;
</code></dd>
525 <h3 id=
"ssection-strings-chars">Strings and characters
</h3>
527 <p>Lisp strings are converted to JavaScript strings.
</p>
530 <dt><code>"foobar"</code></dt>
531 <dd><code>'foobar';
</code></dd>
534 <p>Parenscript makes no effort to interpolate C-style escape
535 strings. Rather, non-printable characters in Lisp strings are
536 output using escape sequences:
</p>
539 <dt><code>#\Tab
</code></dt>
540 <dd><code>'\t';
</code></dd>
542 <dt><code>"\\n"</code></dt>
543 <dd><code>'\\n';
</code></dd>
546 <h3 id=
"ssection-regex">Regular expressions
</h3>
548 <li>(
<code id=
"regex">REGEX
</code> regex)
</li>
552 <dt>regex
</dt> <dd>a string
</dd>
555 <p>Regular expressions can be created by using
556 the
<code>REGEX
</code> form. If the argument does not start with
557 <code>/
</code>, it is surrounded by
<code>/
</code>, otherwise it
558 is left as it is.
</p>
561 <dt><code>(regex
"foobar")
</code></dt>
562 <dd><code>/foobar/;
</code></dd>
564 <dt><code>(regex
"/foobar/i")
</code></dt>
565 <dd><code>/foobar/i;
</code></dd>
568 <p><a href=
"http://weitz.de/cl-interpol/">CL-INTERPOL
</a> is
569 convenient for writing regular expressions:
</p>
572 <dt><code>(regex #?r
"/([^\s]+)foobar/i")
</code></dt>
573 <dd><code>/([^\s]+)foobar/i;
</code></dd>
576 <h3 id=
"ssection-booleans">Booleans and undefined
</h3>
578 <li><code id=
"t">T
</code></li>
579 <li><code id=
"f">F
</code></li>
580 <li><code if=
"false">FALSE
</code></li>
581 <li><code id=
"nil">NIL
</code></li>
582 <li><code id=
"undefined">UNDEFINED
</code></li>
585 <p><code>T
</code> and
<code>FALSE
</code> (or
<code>F
</code>) are
586 converted to their JavaScript boolean
587 equivalents
<code>true
</code> and
<code>false
</code>.
</p>
589 <p><code>NIL
</code> is converted to the JavaScript keyword
590 <code>null
</code>.
</p>
592 <p><code>UNDEFINED
</code> is converted to the JavaScript global
593 variable
<a href=
"https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Properties/undefined"><code>undefined
</code></a>.
</p>
595 <h2 id=
"section-objects">Objects
</h2>
597 <li>(
<code id=
"new">NEW
</code> constructor)
</li>
598 <li>(
<code id=
"create">CREATE
</code> {name value}*)
</li>
599 <li>(
<code id=
"getprop">GETPROP
</code> object {slot-specifier}*)
</li>
600 <li>(
<code id=
"@">@
</code> {slot-specifier}*)
</li>
601 <li>(
<code id=
"chain">CHAIN
</code> {slot-specifier | function-call}*)
</li>
602 <li>(
<code id=
"with-slots">WITH-SLOTS
</code> ({slot-name}*) object body)
</li>
603 <li>(
<code id=
"delete">DELETE
</code> object)
</li>
607 <dt>constructor
</dt> <dd>a function call to an object constructor
</dd>
608 <dt>name
</dt> <dd>symbol, string or keyword
</dd>
609 <dt>value
</dt> <dd>an expression
</dd>
610 <dt>object
</dt> <dd>an expression yielding an object
</dd>
611 <dt>slot-specifier
</dt> <dd>a quoted symbol, a string, a number, or an expression yielding a string or number
</dd>
612 <dt>body
</dt> <dd>implicit
<code>PROGN
</code></dd>
615 <p>The
<code>NEW
</code> operator maps to JavaScript like:
</p>
618 <dt><code>(new (Person age shoe-size))
</code></dt>
619 <dd><code>new Person(age, shoeSize);
</code></dd>
622 <p>Object literals are created
623 with
<code>CREATE
</code>.
<code>CREATE
</code> takes a property
624 list of property names and values.
</p>
627 <dt><code>(create foo
"bar" :blorg
1)
</code></dt>
628 <dd><code>{ foo : 'bar', 'blorg' :
1 };
</code></dd>
631 <pre>(create foo
"hihi"
633 another-object (create :schtrunz
1))
</pre>
639 anotherObject : { 'schtrunz' :
1 } };
</pre>
644 <p>Object properties can be accessed using
645 <code>GETPROP
</code>, which takes an object and a list of
649 <dt><code>(getprop obj 'foo)
</code></dt>
650 <dd><code>obj.foo;
</code></dd>
652 <dt><code>(getprop obj foo)
</code></dt>
653 <dd><code>obj[foo];
</code></dd>
655 <dt><code>(getprop element i 'child-node
0 'node-value)
</code></dt>
656 <dd><code>element[i].childNode[
0].nodeValue;
</code></dd>
659 <p>The convenience macro
<code>@
</code> quotes all its given
660 symbol slot-specifiers to save typing:
</p>
663 <dt><code>(@ an-object foo bar)
</code></dt>
664 <dd><code>anObject.foo.bar;
</code></dd>
666 <dt><code>(@ foo bar child-node
0 node-value)
</code></dt>
667 <dd><code>foo.bar.childNode[
0].nodeValue;
</code></dd>
670 <p><code>CHAIN
</code> can be used to conveniently chain together
671 accessors and function calls:
</p>
674 <dt><code>(chain foo (bar x y)
0 baz)
</code></dt>
675 <dd><code>foo.bar(x, y)[
0].baz;
</code></dd>
678 <p><code>WITH-SLOTS
</code> can be used to bind the given
679 slot-names to a symbol macro that will expand into
680 a
<code>GETPROP
</code> form at expansion time:
</p>
684 <pre>(with-slots (a b c) this
688 <dd><code>this.a + this.b + this.c;
</code></dd>
691 <h2 id=
"section-arrays">Arrays
</h2>
693 <li>(
<code id=
"array">ARRAY
</code> {values}*)
</li>
694 <li>(
<code id=
"list">LIST
</code> {values}*)
</li>
695 <li>(
<code id=
"[]">[]
</code> {values}*)
</li>
696 <li>(
<code id=
"make-array">MAKE-ARRAY
</code> {values}*)
</li>
697 <li>(
<code id=
"length">LENGTH
</code> array)
</li>
698 <li>(
<code id=
"aref">AREF
</code> array index)
</li>
699 <li>(
<code id=
"elt">ELT
</code> array index)
</li>
700 <li>(
<code id=
"destructuring-bind">DESTRUCTURING-BIND
</code> bindings array body)
</li>
701 <li>(
<code id=
"concatenate">CONCATENATE 'STRING
</code> {values}*)
</li>
702 <li>(
<code id=
"append">APPEND
</code> {values}*)
</li>
706 <dt>values
</dt> <dd>an expression
</dd>
707 <dt>array
</dt> <dd>an expression
</dd>
708 <dt>index
</dt> <dd>an expression
</dd>
711 <p>Array literals can be created using the
<code>ARRAY
</code>
712 or
<code>LIST
</code> forms.
</p>
715 <dt><code>(array)
</code></dt>
716 <dd><code>[];
</code></dd>
718 <dt><code>(array
1 2 3)
</code></dt>
719 <dd><code>[
1,
2,
3];
</code></dd>
721 <dt><code>(list (foo) (bar)
3)
</code></dt>
722 <dd><code>[foo(), bar(),
3];
</code></dd>
725 <pre>(array (array
2 3)
726 (array
"foo" "bar"))
</pre>
729 <dd><code>[[
2,
3 ], ['foo', 'bar']];
</code></dd>
732 <p>The
<code>[]
</code> macro treats list arguments as quoted,
733 making it easy to write nested array literals:
</p>
736 <dt><code>([]
1 2 (
3 4)
5 6)
</code></dt>
737 <dd><code>[
1,
2, [
3,
4],
5,
6];
</code></dd>
740 <p>Arrays can also be created with a call to the
<code>Array
</code>
741 function using
<code>MAKE-ARRAY
</code>.
</p>
744 <dt><code>(make-array)
</code></dt>
745 <dd><code>new Array();
</code></dd>
747 <dt><code>(make-array
1 2 3)
</code></dt>
748 <dd><code>new Array(
1,
2,
3);
</code></dd>
753 (make-array
"foobar" "bratzel bub"))
</pre>
756 <dd><code>new Array(new Array(
2,
3), new Array('foobar', 'bratzel bub'));
</code></dd>
759 <p>Array elements can be accessed using
<code>AREF
</code> or
<code>ELT
</code>.
</p>
761 <h2 id=
"section-arithmetic">Arithmetic and boolean operators
</h2>
763 <li>(
<operator
> {argument}*)
</li>
764 <li>(
<single-operator
> argument)
</li>
768 <dt><operator
></dt>
769 <dd>one of
<code>*, /, %, +, -, <<,
>>,
>>>, <
>, EQL,
770 ==, !=, =, ===, !==, &, ^, |, &&, AND, ||, OR
</code>
773 <dt><single-operator
></dt>
774 <dd>one of
<code>INCF, DECF, ++, --, NOT, !
</code></dd>
776 <dt>argument
</dt> <dd>an expression
</dd>
779 <p>Operator forms are similar to function call forms, but have an
780 operator as function name.
</p>
782 <p>Please note that
<code>=
</code> is converted to
<code>==
</code> in
783 JavaScript. The
<code>=
</code> Parenscript operator is not the
784 assignment operator.
</p>
787 <dt><code>(*
1 2)
</code></dt>
788 <dd><code>1 *
2;
</code></dd>
790 <dt><code>(=
1 2)
</code></dt>
791 <dd><code>1 ===
2;
</code></dd>
794 <h2 id=
"section-math">Mathematical functions and constants
</h2>
796 <li>(
<code id=
"max">MAX
</code> {number}*)
</li>
797 <li>(
<code id=
"min">MIN
</code> {number}*)
</li>
798 <li>(
<code id=
"floor">FLOOR
</code> number &optional divisor)
</li>
799 <li>(
<code id=
"ceiling">CEILING
</code> number &optional divisor)
</li>
800 <li>(
<code id=
"round">ROUND
</code> number &optional divisor)
</li>
801 <li>(
<code id=
"sin">SIN
</code> number)
</li>
802 <li>(
<code id=
"cos">COS
</code> number)
</li>
803 <li>(
<code id=
"tan">TAN
</code> number)
</li>
804 <li>(
<code id=
"asin">ASIN
</code> number)
</li>
805 <li>(
<code id=
"acos">ACOS
</code> number)
</li>
806 <li>(
<code id=
"atan">ATAN
</code> number1 &optional number2)
</li>
807 <li>(
<code id=
"sinh">SINH
</code> number)
</li>
808 <li>(
<code id=
"cosh">COSH
</code> number)
</li>
809 <li>(
<code id=
"tanh">TANH
</code> number)
</li>
810 <li>(
<code id=
"asinh">ASINH
</code> number)
</li>
811 <li>(
<code id=
"acosh">ACOSH
</code> number)
</li>
812 <li>(
<code id=
"atanh">ATANH
</code> number)
</li>
813 <li>(
<code id=
"1+">1+
</code> number)
</li>
814 <li>(
<code id=
"1-">1-
</code> number)
</li>
815 <li>(
<code id=
"abs">ABS
</code> number)
</li>
816 <li>(
<code id=
"evenp">EVENP
</code> number)
</li>
817 <li>(
<code id=
"oddp">ODDP
</code> number)
</li>
818 <li>(
<code id=
"exp">EXP
</code> number)
</li>
819 <li>(
<code id=
"expt">EXPT
</code> base power)
</li>
820 <li>(
<code id=
"log">LOG
</code> number &optional base)
</li>
821 <li>(
<code id=
"sqrt">SQRT
</code> number)
</li>
822 <li>(
<code id=
"random">RANDOM
</code> &optional limit)
</li>
824 <li><code id=
"pi">PI
</code></li>
827 <p>The mathematical functions listed above work mostly like their
828 Common Lisp counterparts when called directly, with the
829 exception that complex numbers are not supported. However, most
830 of them are implemented as macros, and as such cannot be treated
831 as first-class functions.
</p>
833 <h2 id=
"section-blocks">Blocks
</h2>
835 <li>(
<code id=
"progn">PROGN
</code> {statement}*) in statement context
</li>
836 <li>(
<code>PROGN
</code> {expression}*) in expression context
</li>
837 <li>(
<code id=
"prog1">PROG1
</code> {expression | statement}*)
</li>
838 <li>(
<code id=
"prog2">PROG2
</code> {expression | statement}*)
</li>
839 <li>(
<code id=
"eval-when">EVAL-WHEN
</code> {expression | statement}*)
</li>
843 <dt>statement
</dt> <dd>a form that compiles to a statement
</dd>
844 <dt>expression
</dt> <dd>a form that compiles to an expression
</dd>
847 <p>The translation of
<code>PROGN
</code> depends on whether it is
848 found in a statement or expression context:
</p>
851 <dt><code>(progn (blorg i) (blafoo i))
</code></dt>
858 <dt><code>(+ i (progn (blorg i) (blafoo i)))
</code></dt>
859 <dd><code>i + (blorg(i), blafoo(i));
</code></dd>
862 <p>The Parenscript
<code>EVAL-WHEN
</code> special operator has a
863 slightly different meaning from the Common Lisp one. The code in
864 the
<code>EVAL-WHEN
</code> special form is assumed to be Common Lisp
865 code in :compile-toplevel and :load-toplevel sitations, and is
866 executed by the Parenscript compiler, and is assumed to be Parenscript
867 code in the :execute situation, when it is run as JavaScript.
</p>
869 <h2 id=
"section-functions">Functions and multiple values
</h2>
871 <li>(
<code id=
"defun">DEFUN
</code> name lambda-list body)
</li>
872 <li>(
<code id=
"lambda">LAMBDA
</code> lambda-list body)
</li>
873 <li>(
<code id=
"flet">FLET
</code> ({(name lambda-list body)}*) body)
</li>
874 <li>(
<code id=
"labels">LABELS
</code> ({(name lambda-list body)}*) body)
</li>
875 <li>(
<code id=
"values">VALUES
</code> {expression}*)
</li>
876 <li>(
<code id=
"multiple-value-bind">MULTIPLE-VALUE-BIND
</code> (var*) expression body)
</li>
877 <li>(
<code id=
"apply">APPLY
</code> function expression*)
</li>
878 <li>(
<code id=
"funcall">FUNCALL
</code> function expression*)
</li>
879 <li><code id=
"this">THIS
</code></li>
883 <dt>expression
</dt> <dd>a form that compiles to an expression
</dd>
884 <dt>name
</dt> <dd>a symbol
</dd>
885 <dt>lambda-list
</dt> <dd>a lambda list
</dd>
886 <dt>body
</dt> <dd>implicit
<code>PROGN
</code></dd>
887 <dt>var
</dt> <dd>a symbol naming a variable
</dd>
888 <dt>function
</dt> <dd>an expression that yields a function
</dd>
891 <p>New function definitions can be introduced using all the
893 -
<code>DEFUN
</code>,
<code>LAMBDA
</code>,
<code>FLET
</code>,
894 and
<code>LABELS
</code>. Function lambda lists
895 support
<code>&optional
</code>,
<code>&rest
</code> and
896 <code>&key
</code> arguments.
</p>
898 <p>The Parenscript multiple value facility passes the first return
899 value using the regular JavaScript convention, therefore functions
900 returning multiple values can be called by regular JavaScript code
901 and
<code>MULTIPLE-VALUE-BIND
</code> works with regular JavaScript
904 <p><code>APPLY
</code> is a macro that expands into a call to the
905 JavaScript
<code>apply
</code> method.
</p>
907 <h2 id=
"section-control-transfer">Control transfer and exceptions
</h2>
909 <li>(
<code id=
"return">RETURN
</code> {value}?)
</li>
910 <li>(
<code id=
"trow">THROW
</code> {exp}?)
</li>
911 <li>(
<code id=
"try">TRY
</code> form
912 {(
<code id=
"catch">:CATCH
</code> (var) body)}?
913 {(
<code id=
"finaly">:FINALLY
</code> body)}?)
</li>
914 <li>(
<code>IGNORE-ERRORS
</code> body)
</li>
918 <dt>value
</dt> <dd>a statement or expression
</dd>
919 <dt>exp
</dt> <dd>an expression
</dd>
920 <dt>var
</dt> <dd>variable to which the value of the caught
<code>THROW
</code> is bound
</dd>
921 <dt>body
</dt> <dd>implicit
<code>PROGN
</code></dd>
924 <p>Parenscript
<code>RETURN
</code> and
<code>THROW
</code> forms do
925 not work like the Common Lisp forms with the same names.
</p>
927 <p><code>RETURN
</code> can only be used to return a value from
928 a function - Parenscript has no analogue of Common Lisp's
929 blocks.
<code>RETURN
</code> works when given either expressions or
930 statements (in which case it performs semantic analysis to
931 determine what should be returned).
</p>
954 <p>Likewise,
<code>THROW
</code> translates directly into the
955 JavaScript
<code>throw
</code>, to be used with
<code>TRY
</code>,
956 which is translated to the JavaScript
<code>try
</code>.
</p>
960 <pre>(try (throw
"i")
962 (alert (+
"an error happened: " error)))
964 (alert
"Leaving the try form")))
</pre>
971 alert('an error happened: ' + error);
973 alert('Leaving the try form');
979 <h2 id=
"section-conditionals">Conditionals
</h2>
981 <li>(
<code id=
"if">IF
</code> condition then {else})
</li>
982 <li>(
<code id=
"when">WHEN
</code> condition then)
</li>
983 <li>(
<code id=
"unless">UNLESS
</code> condition then)
</li>
984 <li>(
<code id=
"cond">COND
</code> {clauses}*)
</li>
985 <li>(
<code id=
"case">CASE
</code> case-value clause*)
</li>
986 <li>(
<code id=
"switch">SWITCH
</code> case-value clause*)
</li>
987 <li><code id=
"break">BREAK
</code></li>
991 <dt>condition
</dt> <dd>an expression
</dd>
992 <dt>then
</dt> <dd>a statement in statement context, or an expression in expression context
</dd>
993 <dt>else
</dt> <dd>a statement in statement context, or an expression in expression context
</dd>
994 <dt>clause
</dt> <dd>(
<value
> body) | (default body)
</dd>
997 <p><code>IF, WHEN, UNLESS
</code> and
<code>COND
</code> work like
998 their Lisp counterparts, and are compiled either into statements
999 or expressions, depending on the context:
</p>
1002 <dt><code>(cond ((= x
1) (+ x (if (foo y)
2 3))))
</code>
1006 x + (foo(y) ?
2 :
3);
1012 <p><code>CASE
</code> works like its Common Lisp equivalent. An
1013 additional form,
<code>SWITCH
</code>, takes the same syntax
1014 as
<code>CASE
</code>, but the individual branches must be
1016 symbol
<a href=
"#break"><code>BREAK
</code></a>. This allows
1017 C-style case
"fall-throughs" in
<code>switch
</code> statements:
</p>
1021 <pre>(switch (aref blorg i)
1022 (
1 (alert
"If I get here"))
1023 (
2 (alert
"I also get here")
1025 (default (alert
"I always get here")))
</pre>
1029 <pre>switch (blorg[i]) {
1031 alert('If I get here');
1033 alert('I also get here');
1036 alert('I always get here');
1042 <p>Note that the default case in a
<code>SWITCH
</code> statement
1043 must be named
<code id=
"default">DEFAULT
</code>.
</p>
1045 <h2 id=
"section-variables">Variable binding and declaration
</h2>
1047 <li>(
<code id=
"let">LET
</code> ({var | (var value)}*) body)
</li>
1048 <li>(
<code id=
"let*">LET*
</code> ({var | (var value)}*) body)
</li>
1049 <li>(
<code id=
"defvar">DEFVAR
</code> var {value}?)
</li>
1050 <li>(
<code id=
"var">VAR
</code> var {value}?)
</li>
1054 <dt>var
</dt> <dd>a symbol
</dd>
1055 <dt>value
</dt> <dd>an expression
</dd>
1056 <dt>body
</dt> <dd>implicit
<code>PROGN
</code></dd>
1057 <dt>object
</dt> <dd>an expression evaluating to an object
</dd>
1060 <p>Parenscript provides the
<code>LET
</code> and
<code>LET*
</code>
1061 special forms for creating new variable bindings. Both special
1062 forms implement lexical scope by renaming the provided variables
1063 via
<a href=
"#ps-gensym"><code>GENSYM
</code></a>, and implement
1065 using
<a href=
"#try"><code>TRY-FINALLY
</code></a>.
</p>
1067 <p>Special variables can be declared using
1068 <code>DEFVAR
</code>. Note that the result is undefined
1069 if
<code>DEFVAR
</code> does not occur as a top-level form.
</p>
1071 <p>One Parenscript feature that is not part of Common Lisp is the
1072 lexically-scoped global variable, which is declared using
1073 the
<code>VAR
</code> special form. The result is undefined
1074 if
<code>VAR
</code> does not occur as a top-level form.
</p>
1076 <p>An example of variable declaration and binding:
</p>
1088 (+ *a* *b* x y))))
</pre>
1103 return A + B + x2 + y;
1112 <h2 id=
"section-assignment">Assignment
</h2>
1114 <p>Parenscript assignment is done via the
1115 standard
<code id=
"setf">SETF
</code>,
<code id=
"SETQ">SETQ
</code>,
1116 <code id=
"PSETF">PSETF
</code>, and
<code id=
"PSETQ">PSETQ
</code>
1117 Lisp special forms. Parenscript supports the Common Lisp
1118 protocol of
<code>SETF
</code>able places.
</p>
1120 <p>New places can be defined in one of two ways: using
1121 <code>DEFSETF
</code> or using
<code>DEFUN
</code> with a setf
1122 function name; both are analogous to their Common Lisp
1123 counterparts.
<code>DEFSETF
</code> supports both long and short
1124 forms, while
<code>DEFUN
</code> of a setf place generates a
1125 JavaScript function name with the
<code>__setf_
</code>
1130 <pre>(defun (setf color) (new-color el)
1131 (setf (@ el style color) new-color))
</pre>
1135 <pre>function __setf_color(newColor, el) {
1136 return el.style.color = newColor;
1141 <dt><code>(setf (color some-div) (+
23 "em"))
</code></dt>
1143 <pre>var _js2 = someDiv;
1144 var _js1 =
23 + 'em';
1145 __setf_color(_js1, _js2);
</pre>
1150 <p>The following example illustrates how setf places can be used
1151 to provide a uniform protocol for positioning elements in HTML
1156 <pre>(defsetf left (el) (offset)
1157 `(setf (@ ,el style left) ,offset))
1160 `(@ ,el offset-left))
1162 (setf (left some-div) (+
123 "px"))
1163 (left some-div)
</pre>
1167 <pre>var _js2 = someDiv;
1168 var _js1 =
123 + 'px';
1169 _js2.style.left = _js1;
1170 someDiv.offsetLeft;
</pre>
1175 <h2 id=
"section-iteration">Iteration
</h2>
1177 <li>(
<code id=
"do">DO
</code> ({var | (var {init}? {step}?)}*) (end-test {result}?) body)
</li>
1178 <li>(
<code id=
"do*">DO*
</code> ({var | (var {init}? {step}?)}*) (end-test {result}?) body)
</li>
1179 <li>(
<code id=
"dotimes">DOTIMES
</code> (var numeric-form {result}?) body)
</li>
1180 <li>(
<code id=
"dolist">DOLIST
</code> (var list-form {result}?) body)
</li>
1181 <li>(
<code id=
"for-in">FOR-IN
</code> (var object) body)
</li>
1182 <li>(
<code id=
"while">WHILE
</code> end-test body)
</li>
1183 <li>(
<code id=
"loop">LOOP
</code> {loop clauses}*)
</li>
1187 <dt>var
</dt> <dd>a symbol
</dd>
1188 <dt>numeric-form
</dt> <dd>a number yielding expression
</dd>
1189 <dt>list-form
</dt> <dd>an array yielding expression
</dd>
1190 <dt>object-form
</dt> <dd>an object yielding expression
</dd>
1191 <dt>init
</dt> <dd>an expression
</dd>
1192 <dt>step
</dt> <dd>an expression
</dd>
1193 <dt>end-test
</dt> <dd>an expression
</dd>
1194 <dt>result
</dt> <dd>an expression
</dd>
1195 <dt>body
</dt> <dd>implicit
<code>PROGN
</code></dd>
1198 <p>Parenscript comes with a wide array of Common Lisp iteration
1199 constructs that compile to efficient JavaScript code,
1200 including a partial implementation of
<code>LOOP
</code>.
</p>
1202 <h2 id=
"section-macros">Macros
</h2>
1203 <h3 id=
"ssection-defining-macros">Defining macros
</h3>
1205 <li>(
<code id=
"defmacro">DEFMACRO
</code> name lambda-list macro-body)
</li>
1206 <li>(
<code id=
"defpsmacro">DEFPSMACRO
</code> name lambda-list macro-body)
</li>
1207 <li>(
<code id=
"defmacro+ps">DEFMACRO+PS
</code> name lambda-list macro-body)
</li>
1208 <li>(
<code id=
"import-macros-from-lisp">IMPORT-MACROS-FROM-LISP
</code> symbol*)
</li>
1209 <li>(
<code id=
"macrolet">MACROLET
</code> ({name lambda-list macro-body}*) body)
</li>
1213 <dt>name
</dt> <dd>a symbol
</dd>
1214 <dt>lambda-list
</dt> <dd>a lambda list
</dd>
1215 <dt>macro-body
</dt> <dd>Lisp code evaluating to Parenscript code
</dd>
1216 <dt>body
</dt> <dd>implicit
<code>PROGN
</code></dd>
1217 <dt>symbol
</dt> <dd>symbol with a Lisp macro function definition
</dd>
1220 <p>Parenscript macros are like Lisp macros in that they have
1221 access to the full Lisp language, but different in that they must
1222 produce Parenscript code. Since Parenscript provides a large
1223 subset of Common Lisp, many Lisp macros already produce valid
1224 Parenscript code, and vice-versa. Parenscript provides several
1225 different ways to define new macros, and to use already existing
1226 Common Lisp macros.
</p>
1228 <p><code>DEFMACRO
</code> and
<code>MACROLET
</code> can be used to
1229 define new macros in Parenscript code. Note that macros defined
1230 this way are defined in a null lexical environment (ex
1231 -
<code>(let ((x
1)) (defmacro baz (y) `(+ ,y ,x)))
</code> will
1232 not work), since the surrounding Parenscript code is just
1233 translated to JavaScript and not actually evaluated.
</p>
1235 <p><code>DEFPSMACRO
</code> is a Lisp form (not a Parenscript one!)
1236 that can be used by Lisp code to define Parenscript macros without
1237 calling the Parenscript compiler.
</p>
1239 <p>The representation of Parenscript macro functions is the same
1240 as that of Common Lisp, and in fact Parenscript can use already
1241 defined macros this way.
1243 <p><code>DEFMACRO+PS
</code> defines two macros with the same name
1244 and expansion, one in Parenscript and one in
1245 Lisp.
<code>DEFMACRO+PS
</code> is used when the full macroexpansion of
1246 the Lisp macro yields code that cannot be used by Parenscript.
</p>
1248 <p>Parenscript also supports the use of macros defined in the
1249 underlying Lisp environment. Existing Lisp macros can be imported into
1250 the Parenscript macro environment
1251 by
<code>IMPORT-MACROS-FROM-LISP
</code>. This functionality enables
1252 code sharing between Parenscript and Lisp, and is useful in debugging
1253 since the full power of Lisp macroexpanders, editors and other
1254 supporting facilities can be used. However, it is important to note
1255 that the macroexpansion of Lisp macros and Parenscript macros takes
1256 place in their own respective environments, and many Lisp macros
1257 (especially those provided by the Lisp implementation) expand into
1258 code that is not usable by Parenscript. To make it easy for users to
1259 take advantage of these features, two additional macro definition
1260 facilities are provided by Parenscript:
</p>
1262 <h3 id=
"ssection-symbol-macros">Symbol macros
</h3>
1263 (
<code id=
"define-ps-symbol-macro">DEFINE-PS-SYMBOL-MACRO
</code> symbol expansion)
1264 (
<code id=
"symbol-macrolet">SYMBOL-MACROLET
</code> ({name macro-body}*) body)
1266 <p>Symbol macros can be introduced using
<code>SYMBOL-MACROLET
</code>
1267 or defined in Lisp with
<code>DEFINE-PS-SYMBOL-MACRO
</code>. For
1268 example, the Parenscript
1269 <code>WITH-SLOTS
</code> is implemented using symbol macros:
</p>
1272 (defpsmacro with-slots (slots object &rest body)
1273 `(symbol-macrolet ,(mapcar #'(lambda (slot)
1274 `(,slot '(getprop ,object ',slot)))
1279 <h3 id=
"ssection-gensym">Gensym
</h3>
1281 <li>(
<code id=
"ps-gensym">PS-GENSYM
</code> {string})
</li>
1282 <li>(
<code id=
"with-ps-gensyms">WITH-PS-GENSYMS
</code> symbols &body body)
</li>
1283 <li>(
<code id=
"ps-once-only">PS-ONCE-ONLY
</code> (&rest vars) &body body)
</li>
1285 <li><code id=
"*ps-gensym-counter*">*PS-GENSYM-COUNTER*
</code></li>
1288 <p>JavaScript identifier equality is based on string
1289 representations, as opposed to Common Lisp, where two uninterned
1290 symbols with the same name are different objects. Therefore
1291 Parenscript
<code>GENSYM
</code> depends
1292 on
<code>*PS-GENSYM-COUNTER*
</code> values only for generating
1293 unique identifiers.
<code>*PS-GENSYM-COUNTER*
</code> does not
1294 persist and is not guaranteed to be thread-safe, so care should be
1295 taken to avoid writing code where gensymed identifiers may clash
1296 (for example, this could happen if you concatenate JS code from PS
1297 compilers running in two different Lisp images, where the values
1298 of
<code>*PS-GENSYM-COUNTER*
</code> overlap).
1300 <h2 id=
"section-utilities">Utilities
</h2>
1302 <h3 id=
"ssection-dom">DOM
</h3>
1304 <li>(
<code>INNER-HTML
</code> el)
</li>
1305 <li>(
<code>URI-ENCODE
</code> el)
</li>
1306 <li>(
<code>ATTRIBUTE
</code> el)
</li>
1307 <li>(
<code>OFFSET
</code> compass el)
</li>
1308 <li>(
<code>SCROLL
</code> compass el)
</li>
1309 <li>(
<code>INNER
</code> wh el)
</li>
1310 <li>(
<code>CLIENT
</code> wh el)
</li>
1314 <dt>el
</dt> <dd>an expression that yields a DOM element
</dd>
1315 <dt>compass
</dt> <dd>one of
<code>:TOP, :LEFT, :HEIGHT, :WIDTH, :BOTTOM, :RIGHT
</code></dd>
1316 <dt>wh
</dt> <dd>one of
<code>:WIDTH, :HEIGHT
</code></dd>
1319 <h3 id=
"ssection-html-gen">HTML generation
</h3>
1321 <li>(
<code id=
"ps-html">PS-HTML
</code> html-expression)
</li>
1322 <li>(
<code id=
"who-ps-html">WHO-PS-HTML
</code> html-expression)
</li>
1323 <li><code id=
"*ps-html-empty-tag-aware-p*">*PS-HTML-EMPTY-TAG-AWARE-P*
</code></li>
1324 <li><code id=
"*ps-html-mode*">*PS-HTML-MODE*
</code></li>
1327 <p>Parenscript comes with two HTML markup generation facilities
1328 that produce Parenscript code -
<code>PS-HTML
</code>
1329 and
<code>WHO-PS-HTML
</code>. The former
1330 accepts
<a href=
"http://opensource.franz.com/aserve/htmlgen.html">LHTML
</a>
1331 style markup, while the latter
1332 accepts
<a href=
"http://weitz.de/cl-who/">CL-WHO
</a> style
1335 <p><code>*PS-HTML-EMPTY-TAG-AWARE-P*
</code>
1336 and
<code>*PS-HTML-MODE*
</code> control how tags are closed when an
1338 content. When
<code>*PS-HTML-EMPTY-TAG-AWARE-P*
</code> is nil, all
1339 tags are fully closed (ex -
<code>:BR
</code> is translated
1340 as
<code><BR
></BR
></code>). When
<code>*PS-HTML-EMPTY-TAG-AWARE-P*
</code>
1341 has a non-nil value and
<code>*PS-HTML-MODE*
</code>
1342 is
<code>:SGML
</code>, tags such as
<code>BR
</code> are output without
1343 being closed; when
<code>*PS-HTML-MODE*
</code> is
<code>:XML
</code>,
1344 the XML-style closing tags are used (ex -
<code>:BR
</code> is
1345 translated as
<code><BR /
></code>).
</p>
1348 <dt><code>(ps-html ((:a :href
"foobar")
"blorg"))
</code></dt>
1349 <dd><code>'
<A HREF=\
"foobar\">blorg
</A
>';
</code></dd>
1351 <dt><code>(who-ps-html (:a :href (generate-a-link)
"blorg"))
</code></dt>
1352 <dd><code>'
<A HREF=\
"' + generateALink() + '\">blorg
</A
>';
</code></dd>
1355 <p>The Parenscript compiler can be recursively called in an HTML
1360 <pre>((@ document write)
1361 (ps-html ((:a :href
"#"
1362 :onclick (ps-inline (transport)))
"link")))
</pre>
1365 <dd><code>document.write('
<A HREF=\
"#\" ONCLICK=\
"' + ('javascript:' + 'transport()') + '\">link
</A
>');
</code></dd>
1368 <p>Forms may be used in attribute lists to conditionally generate
1369 the next attribute. In this example the textarea is sometimes
1374 <pre>(let ((disabled nil)
1376 (setf (@ element inner-h-t-m-l)
1377 (ps-html ((:textarea (or disabled (not authorized)) :disabled
"disabled")
1383 <pre>var disabled = null;
1384 var authorized = true;
1387 + (disabled || !authorized ? ' DISABLED=\
"' + 'disabled' + '\"' : '')
1388 + '
>Edit me
</TEXTAREA
>';
</pre>
1393 <h2 id=
"section-runtime-library">Runtime library
</h2>
1395 <li>(
<code id=
"">MEMBER
</code> object array)
</li>
1396 <li>(
<code id=
"">MAP
</code> function array)
</li>
1397 <li>(
<code id=
"">MAPCAR
</code> function {array}*)
</li>
1398 <li>(
<code id=
"">REDUCE
</code> function array object)
</li>
1399 <li>(
<code id=
"">MAP-INTO
</code> function array)
</li>
1400 <li>(
<code id=
"">SET-DIFFERENCE
</code> array1 array2)
</li>
1401 <li><code id=
"*ps-lisp-library*">*PS-LISP-LIBRARY*
</code></li>
1404 <p>All the Parenscript constructs presented so far have been free
1405 of any runtime dependencies. Parenscript also comes with a library
1406 of useful predefined functions that can be added to your
1407 project. These functions are kept as Parenscript code in
1408 the
<code>*PS-LISP-LIBRARY*
</code> special variable.
</p>
1410 <p><code>MAP
</code> differs from its Common Lisp counterpart by
1411 virtue of being a
<code>MAPCAR
</code> that only accepts a single
1412 sequence to map over.
<code>MAP-UNTIL
</code> is
1413 like
<code>MAP
</code> but replaces the contents of the given
1416 <h2 id=
"section-slime-integration">SLIME integration
</h2>
1418 <p>The
<code>extras
</code> folder in the Parenscript distribution
1419 contains
<code>js-expander.el
</code>, which when loaded in Emacs
1420 with SLIME adds the ability to quickly see the translation of
1421 any Lisp form in JavaScript, and works much like the Slime '
<code>C-c
1422 M-m
</code>' macroexpansion feature.
</p>
1424 <p>'
<code>C-c j
</code>' (
<a href=
"#ps"><code>PS
</code></a>) or
1425 '
<code>C-c d
</code>' (
<a href=
"#ps-doc"><code>PS-DOC
</code></a>)
1426 at a ParenScript expression in a
<code>slime-mode
</code> buffer
1427 will bring up a buffer with the resulting Javascript code. Note
1428 that the extension does not work
1429 in
<code>slime-repl-mode
</code>, which is intentional.
</p>
1431 <p style=
"font-size:xxx-small"><i>Last modified:
2012-
07-
27</i></p>