Special Forms and Macros of Jscheme
Special Forms and Macros inherited from Scheme
Jscheme adopts the standard special forms and macros of R4RS Scheme
and adds a few (in blue) to improve the Java interface (e.g. tryCatch)
(quote EXPR) or
' EXPR -- intuitively, the
quote indicates that the EXPR is to be treated as data
and should not be evaluated. The precise semantics are a little
more involved as we must state what syntax is allowed inside
(e.g. quotes, Java Literals, vectors, ...) and how that syntax
(begin EXPR1 EXPR2 ... EXPRn) -- this
evaluates the expressions in order, first EXPR1, then EXPR2. The value
of the last expression is returned. The non-final expresssions only affect
program state by their side effects.
(if EXPR1 EXPR2 EXPR3) -- this first
evaluates EXPR1 to get a value V. If V is equal to the boolean value #f, then
EXPR2 is evaluated, otherwise EXPR3 is evaluated.
(if EXPR1 EXPR2) -- this is implemented as
(if EXPR1 EXPR2 #f)
(or EXPR1 EXPR2 ...) -- The expressions are
evaluated in order until either one evaluates to a value V not equal to #f or
all expressions are evaluated. In the former case, V is returned, in the latter
#f is returned.
(and EXPR1 EXPR2 ...) -- The expressions are
evaluated in order until one of the expressions evaluates to #f or the end of
the list is reached. If there are no expressions, then #t is returned; otherwise,
the value of the last expression to be evaluated is returned.
(set! VAR EXPR) -- Here VAR must be a global
or local scheme variable or a Java Literal
representing a static Java variable.
In each case, the EXPR is evaluated and its value is assigned to the variable.
(define VAR EXPR ) -- This adds the VAR to the
(local or global) environment, and assigns it the value V obtained by evaluating EXPR.
(define (VAR0 VAR1 ... VARN) EXPR1 ... EXPRN ) -- this
is equivalent to
(define VAR0 (lambda (VAR1 ... VARN) EXPR1 ... EXPRN ))
(lambda (V1 ... VN) EXPR1 ... EXPRM) -- this creates
a closure C. When the closure is applied to N values A1 ... An, a new environment is
created in which Ai is bound to Vi, and the expressions are evaluated in order, the
value of the last expression is returned.
(lambda (V1 ... VN . R) EXPR1 ... EXPRM) --
This closure can be applied to a N or more arguments. R is then bound to the list containing
all arguments after the Nth.
(lambda R EXPR1 ... EXPRM) -- This closure
can be applied to a list of 0 or more arguments. R is bound to the list of arguments.
(cond (EXPR1a EXPR1b ... EXPR1z) .... (EXPRNa ... EXPRNz))
(quasiquote EXPR) or
` EXPR -- the quasiquote
(unquote EXPR) or
, EXPR -- (must appear in quasiquoted expression)
(unquote-splicing EXPR) or
,@ EXPR -- (must appear in quasiquoted expression)
(let ((V1 EXPR1) .... (Vn EXPRN)) E1 ... EM)
(let V0 ((V1 EXPR1) .... (Vn EXPRN)) E1 ... EM)
(let* ((V1 EXPR1) .... (Vn EXPRN)) E1 ... EM)
(letrec ((V1 EXPR1) .... (Vn EXPRN)) E1 ... EM)
(case EXPR ((C1a ... C1z) EXPR1) .... (Vn EXPRN)) E1 ... EM)
(do ((V1 EXPR1) .... (Vn EXPRN)) E1 ... EM)
Jscheme Extensions to the Control Structure of Scheme
(tryCatch EXPR F) this evaluates the EXPR to obtain
a return value V; if, however, a Java exception E is thrown, it calls (F E) to obtain
a return value, e.g.,
(define (string->double S)
(tryCatch (Double. S) (lambda (e)
(throw (RuntimeError. "Number format error")))))
(string->double "1.2e 3")
(define-macro name (lambda ...))
When the macro "name" is applied to its arguments, it generates an expression
which is then passed back to the evaluator.
(define-macro (newif Test Then Else) `(if ,Test ,Then ,Else))
(define-macro when (lambda (Test . Actions) `(if ,Test (begin . ,Actions))))
- Thunks are runnable objects.
This allows Jscheme to easily implement multi-threading.
(define (loop N D)
(tryCatch (begin (Thread.sleep D) (display N) (newline) (loop (+ N 1) D))
(lambda (e) (display (list "thread interrupted" e)) (newline))))
(define s (Thread. (lambda() (loop 0 1000L))))
(define t (Thread. (lambda() (loop 0 5000L))))
(define-method ....) -- this has the same syntax as define
except that the parameters can have the form (NAME Type) instead of just NAME, where Type is a
Java class name, e.g.
(define-method (iterate (items Iterator) action)
(if (.hasNext items)
(begin (action (.next items))
(iterate items action))))
(define-method (iterate (items Collection) action)
(iterate (.iterator items) action))
(define-method (iterate (items Map) action)
(iterate (.entrySet items) action))
(define-method (iterate (items jsint.Pair) action)
(action (car items))
(let ((items (cdr items)))
(if (pair? items) (iterate items action))))
(define-method (iterate (items Object) action)
(let loop ((i 0)
(L (vector-length items)))
(if (< i L) (begin (action (vector-ref items i)) (loop (+ i 1) L)))))
(define (printit x) (.println System.$out x))
(iterate '(1 2 3 4) printit)
(iterate (list->vector '(1 2 3 4)) printit)
(time EXPR [OptionalNumRepeats]) This little
macro lets you time operations.