eval refitted
This commit is contained in:
+53
-10
@@ -83,8 +83,11 @@ self-call.
|
||||
|
||||
The generator is best understood as a source-to-source translator over syntax.
|
||||
The input is converted to datum form and matched against the supported surface
|
||||
language. The Racket code is not evaluated. This has a few important
|
||||
consequences:
|
||||
language. The Racket code is normally not evaluated. The deliberate exception
|
||||
is @racket[(eval racket-expr)], which interpolates a Racket value into the
|
||||
JavaScript source text. The expression is evaluated in the lexical context of
|
||||
the @racket[js] or @racket[js/expression] use and its value is emitted as a
|
||||
JavaScript literal. This has a few important consequences:
|
||||
|
||||
@compact-items[
|
||||
@item{Only forms known to js-maker are translated specially. Unknown calls are
|
||||
@@ -100,6 +103,46 @@ consequences:
|
||||
helper functions/IIFEs to preserve semantics.}
|
||||
]
|
||||
|
||||
@subsection{Racket value interpolation with eval}
|
||||
|
||||
The form @racket[(eval racket-expr)] is an interpolation escape hatch inherited
|
||||
from the original transformer. It evaluates @racket[racket-expr] as Racket in
|
||||
the use-site lexical context and then splices the resulting value into the
|
||||
JavaScript source as a literal. This makes surrounding Racket bindings visible
|
||||
to the interpolation expression.
|
||||
|
||||
@(rkt+js
|
||||
#<<RKT
|
||||
(let ([x 10]
|
||||
[y 20])
|
||||
(js (let ([a (eval (* x y))])
|
||||
(return (* a a)))))
|
||||
RKT
|
||||
#<<JS
|
||||
{
|
||||
let a = 200;
|
||||
return (a * a);
|
||||
}
|
||||
JS
|
||||
)
|
||||
|
||||
@(rkt+js
|
||||
#<<RKT
|
||||
(js/expression (array (eval (+ 1 2))
|
||||
(eval (string-append "a" "b"))))
|
||||
RKT
|
||||
#<<JS
|
||||
[3, "ab"]
|
||||
JS
|
||||
)
|
||||
|
||||
This is not JavaScript @tt{eval}. To call JavaScript @tt{eval}, call the
|
||||
JavaScript function explicitly, for example @racket[(send window eval "1 + 2")].
|
||||
Racket-side @racket[eval] is best used for constants, generated literal data,
|
||||
and small configuration values that are known while the JavaScript source is
|
||||
being constructed. It should not be used for run-time browser state, DOM access,
|
||||
or user input.
|
||||
|
||||
@section{Supported expression and statement forms}
|
||||
|
||||
The following Racket forms are supported as either expressions, statements, or
|
||||
@@ -116,6 +159,7 @@ both, depending on context:
|
||||
@item{@racket[when], @racket[unless], @racket[while], @racket[for],
|
||||
@racket[for/list], @racket[for/vector], and @racket[for/fold].}
|
||||
@item{@racket[with-handlers] for the generic @racket[exn?] case.}
|
||||
@item{@racket[(eval racket-expr)] for Racket-side value interpolation into JavaScript literals.}
|
||||
@item{Interop forms such as @racket[send], @racket[new], @racket[js-ref],
|
||||
@racket[js-dot], @racket[set-prop!], @racket[delete-prop!],
|
||||
@racket[js-delete], @racket[array], @racket[object],
|
||||
@@ -732,14 +776,13 @@ harness rather than hiding raw JavaScript inside the feature implementation.
|
||||
|
||||
@section{Further examples}
|
||||
|
||||
The companion document @filepath{scrbl/usecases.scrbl} contains practical
|
||||
examples such as DOM manipulation, @tt{Set}, currying, object destructuring,
|
||||
timers, @tt{fetch}, sorting, binary search, and map-based counting. Each use
|
||||
case shows the Racket/js-maker source, representative JavaScript output, and the
|
||||
behavior tested by the regression suite.
|
||||
The companion @hyperlink["../usecases/index.html"]{use-case manual} contains
|
||||
practical examples such as DOM manipulation, @tt{Set}, currying, object
|
||||
destructuring, timers, @tt{fetch}, sorting, binary search, and map-based
|
||||
counting. Each use case shows the Racket/js-maker source, representative
|
||||
JavaScript output, and the behavior tested by the regression suite.
|
||||
|
||||
When the documentation is rendered with @exec{raco scribble}, the use-case
|
||||
manual is normally emitted as a separate document next to this one. The explicit
|
||||
file name is used here instead of a cross-document reference because the latter
|
||||
The source file for that companion manual is @filepath{scrbl/usecases.scrbl}.
|
||||
The relative link above is used instead of @racket[other-doc] because the latter
|
||||
can render as an unresolved @tt{(part ... "top")} tag when the two documents are
|
||||
built outside Racket's installed documentation index.
|
||||
|
||||
Reference in New Issue
Block a user