[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The multiple-value feature was added in R5RS.
lambda
,
cf section 4.1.4 of the R5RS.
The expressions are evaluated in the current environment, the variables of the formals are bound to fresh locations, the return values of the expressions are stored in the variables, the body is evaluated in the extended environment, and the values of the last expression of body are returned. The body is a "tail body", cf section 3.5 of the R5RS.
The matching of each formals to values is as for the matching of
formals to arguments in a ambda
expression, and it is an
error for an expression to return a number of values that does not
match its corresponding formals.
(let-values ((a b . c) (values 1 2 3 4))) (list a b c)) --> (1 2 (3 4)) (let ((a 'a) (b 'b) (x 'x) (y 'y)) (let-values (((a b) (values x y)) ((x y) (values a b))) (list a b x y))) --> (x y a b) |
Each formals should be a formal arguments list as for a
lambda
expression, cf section 4.1.4 of the R5RS.
let*-values
is similar to let-values
, but the bindings are
performed sequentially from left to right, and the region of a binding
indicated by (formals expression) is that part of the
let*-values
expression to the right of the binding. Thus the
second binding is done in an environment in which the first binding is
visible, and so on.
(let ((a 'a) (b 'b) (x 'x) (y 'y)) (let*-values (((a b) (values x y)) ((x y) (values a b))) (list a b x y))) --> (x y x y) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Note that if the Scheme reader sees this literal at top-level,
it is returned literally. This is indistinguishable from
coming to the end of the input file. If you do not want to end reading,
but want the actual value of #!eof
, you should quote it.
(values)
.
If this is the value of an expression in a read-eval-print loop,
nothing is printed.
null
value. This is not really a Scheme value,
but is useful when interfacing to low-level Java code.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Keywords are similar to symbols. The main difference is that keywords are self-evaluating and therefore do not need to be quoted in expressions. They are used mainly for specifying keyword arguments.
keyword = identifier: |
An alternative syntax, with the colon first, is supported for compatibility with Common Lisp and some other Scheme implementations:
keyword = :identifier |
Putting the colon first has exactly the same effect as putting it last; putting is last is recommended, and is how keywords are printed.
A keyword is a single token; therefore no whitespace is allowed between the identifier and the colon (which is not considered part of the name of the keyword).
#t
if obj is a keyword, and otherwise returns #f
.
#\:
.
#\:
.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(proc arg1 ...)
, unless proc and
all the following arguments are compile-time constants.
(That is: They are either constant, or symbols that have a global
binding and no lexical binding.) In that case, proc
is applied to the arguments at compile-time, and the result replaces
the constant-fold
form. If the application raises an exception,
a compile-time error is reported.
For example:
(constant-fold vector 'a 'b 'c) |
(quote #(a b c))
, assuming vector
has not been re-bound.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can associate arbitrary properties with any procedure. Each property is a (key, value)-pair. Usually the key is a symbol, but it can be any object.
The system uses certain internal properties:
'name
refers to the name used when a procedure is printed;
'emacs-interactive
is used to implement Emacs interactive
specification;
'setter
will be (not yet implemented) used to associate a setter
prcedure.
#f
) instead.
To change the print name of the standard +
procedure (probably
not a good idea!), you could do:
(set-procedure-property! + 'name 'PLUS) |
+ => #<procedure PLUS> (+ 2 3) => 5 (PLUS 3 4) => ERROR |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A generic procedure is a collection of method procedures. (A "method procedure" is not the same as a Java method, but the terms are related.) You can call a generic procedure, which selects the "closest match" among the component method procedures: I.e. the most specific method procedure that is applicable give the actual arguments.
The keywords specify how the arguments are used.
A method:
keyword is optional and specifies that the following
argument is a method.
A name:
keyword specifies the name of the resulting procedure,
when used for printing.
Unrecognized keywords are used to set the procedure properties of the result.
(define plus10 (make-procedure foo: 33 name: 'Plus10 method: (lambda (x y) (+ x y 10)) method: (lambda () 10))) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The formal arguments list of a lambda expression has two extendsions over standard Scheme: Kawa borrows the extended formal argument list of DSSSL, and Kawa allows you to declare the type of the parameter.
lambda-expression = (lambda formals [rtype] body) |
formals = (formal-arguments) | rest-arg |
define
:
(define (name formal-arguments) [rtype] body) |
formal-arguments = req-opt-args (rest-key-args | . rest-arg) |
req-opt-args = req-arg ... [#!optional opt-arg ...] rest-key-args = [#!rest rest-arg] [#key key-arg ...] req-arg = variable [:: type] | (variable [[::] type] ) opt-arg = arg-with-default key-arg = arg-with-default arg-with-default = variable [:: type] | ( variable [:: type [initializer] | initializer [[::] type]] ) rest-arg = variable |
When the procedure is applied to a list of actual arguments, the formal and actual arguments are processed from left to right as follows:
#f
. The initializer is evaluated in an
environment in which all the previous formal parameters have been bound.
#!key
was specified, then there shall be an even number of
remaining actual arguments. These are interpreted as a series of pairs,
where the first member of each pair is a keyword specifying the argument name,
and the second is the corresponding value. It shall be an error if the first
member of a pair is not a keyword. It shall be an error if the argument name
is not the same as a variable in a key-args, unless there
is a rest-arg. If the same argument name occurs more than once
in the list of actual arguments, then the first value is used.
If there is no actual argument for a particular key-arg,
then the variable is bound
to the corresponding initializer, if one was specified, and
otherwise to #f
. The initializer is evaluated in an
environment in which all the previous formal parameters have been bound.
If a type is specified, the corresponding actual argument (or the initializer default value) is coerced to the specified type. In the function body, the parameter has the specified type.
If rtype (the first form of the function body) is an unbound
identifier of the form <TYPE>
(that is the first character
is `<' and the last is `>'), then tha specifies the
functions return type. It is syntactic sugar for
(as <TYPE> (begin BODY))
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
As a super-class of numbers, Kawa also provides quantities. A quantity is a product of a unit and a pure number. The number part can be an arbitrary complex number. The unit is a product of integer powers of base units, such as meter or second.
Kawa quantities are a generalization of the quantities in DSSSL, which only has length-derived quantities.
The precise syntax of quantity literals may change,
but some examples are 10pt
(10 points), 5s
(5 seconds),
and 4cm^2
(4 square centimeters).
complex?
.
"cm"
or "s"
(seconds).
(define-base-unit dollar "Money") |
(define-unit cent 0.01dollar) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These functions operate on the 2's complement binary representation of an exact integer.
(not (zero? (logand i j)))
,
but is more efficient.
#t
iff the bit numbered pos in i is one.
j>0
, and
a "right" shift if j<0
.
The result is equal to (floor (* i (expt 2 j)))
.
arithmetic-shift
.
(arithmetic-shift (bitand n (bitnot (arithmetic-shift -1 end))) (- start))
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Uniform vectors are vectors whose elements are of the same numeric type.
The are defined by SRFI-4.
However, the type names (such as <s8vector>
) are a Kawa extension.
<byte>
.
<byte>
,
but each element is treated as if unsigned.
<short>
.
<short>
,
but each element is treated as if unsigned.
<int>
.
<int>
,
but each element is treated as if unsigned.
<long>
.
<long>
,
but each element is treated as if unsigned.
<float>
.
<double>
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
#f
on error, but may change to be more compatible
with scsh.)
"kawa~d.tmp"
) to generate
a unique filename in (system-tmpdir)
.
The current implementation is not safe from race conditions;
this will be fixed in a future release (using Java2 features).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
'trim
, ignores the delimiter;
'peek
leaves the delimiter in the input stream;
'concat
appends the delimiter to the returned value;
and 'split
returns the delimiter as a second value.
You can use the last three options to tell if the string was
terminated by end-or-line or by end-of-file.
close-input-port
,
though its storage will be reclaimed by the
garbage collector if it becomes inaccessible.
(define p (open-input-string "(a . (b c . ())) 34")) (input-port? p) --> #t (read p) --> (a b c) (read p) --> 34 (eof-object? (peek-char p)) --> #t |
get-output-string
.
The port can be closed by the procedure close-output-port
,
though its storage will be reclaimed by the garbage collector
if it becomes inaccessible.
(let ((q (open-output-string)) (x '(a b c))) (write (car x) q) (write (cdr x) q) (get-output-string q)) --> "a(b c)" |
open-output-string
,
returns a string consisting of the characters that have been
output to the port so far.
(current-output-port)
.
An interactive input port has a prompt procedure associated with it. The prompt procedure is called before a new line is read. It is passed the port as an argument, and returns a string, which gets printed as a prompt.
"#|kawa:L|# "
, where
L is the current line number of port.
When reading a continuation line, the result
is "#|C---:L|# "
, where C
is the character returned
by (input-port-read-state port)
.
The prompt has the form of a comment to make it easier to cut-and-paste.
#f
. Otherwise,
the result is a 0-origin integer - i.e. the first character
of the first line is line 0, column 0. (However, when you
display a file position, for example in an error message,
we recommend you add 1 to get 1-origin integers. This is
because lines and column numbers traditionally start with
1, and that is what non-programmers will find most natural.)
(+ 1 (port-line port))
.
(set-port-line! port (- num 1))
.
(+ 1 (port-column port))
.
read
state of the port.
Returns #\Return
if not current doing a read,
#\"
if reading a string; #\|
if reading a comment; #\(
if inside a list; and #\Space
when otherwise in a read
.
The result is intended for use by prompt prcedures, and is not necessarily
correct except when reading a new-line.
read
handles letters when reading a symbol.
If the first letter is `U', then letters in symbols are upper-cased.
If the first letter is `D' or `L', then letters
in symbols are down-cased.
If the first letter is `I', then the case of letters in symbols
is inverted.
Otherwise (the default), the letter is not changed.
(Letters following a `\' are always unchanged.)
port-char-encoding
is #f
, the file is assumed
to be a binary file and no conversion is done.
Otherwise, the file is a text file. The default is #t
, which
uses a locale-dependent conversion. If port-char-encoding
is a symbol, it must be the name of a character encoding known to Java.
For all text files (that is if port-char-encoding
is not #f
),
on input a #\Return
character or
a #\Return
followed by #\Newline
are converted into plain #\Newline
.
This variable is checked when the file is opened; not when actually reading or writing. Here is an example of how you can safely change the encoding temporarily:
(define (open-binary-input-file name) (fluid-let ((port-char-encoding #f)) (open-input-file name))) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Returns #t
, #f
or a string; has side effect of printing
according to fmt. If destination is #t
,
the output is to the current output port and #t
is returned. If
destination is #f
, a formatted string is returned as the
result of the call. If destination is a string,
destination is regarded as the format string; fmt is
then the first argument and the output is returned as a string. If
destination is a number, the output is to the current error port
if available by the implementation. Otherwise destination must be
an output port and #t
is returned.
fmt must be a string or an instance of gnu.text.MessageFormat
or java.text.MessageFormat
. If fmt is a string,
it is parsed as if by parse-format
.
format-string
, which is a string of the form of a Common LISP
format description. Returns an instance of gnu.text.ReportFormat
,
which can be passed to the format
function.
A format string passed to format
or parse-format
consists of format directives (that start with `~'),
and regular characters (that are written directly to the destination).
Most of the Common Lisp (and Slib) format directives are implemented.
Neither justification, nor pretty-printing are supported yet.
Plus of course, we need documentation for format
!
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Documentation syntax: Uppercase characters represent the corresponding control directive characters. Lowercase characters represent control directive parameter descriptions.
~A
display
does).
~@A
~mincol,colinc,minpad,padcharA
~S
write
does).
~@S
~mincol,colinc,minpad,padcharS
~C
~@C
#\
prefixing).
~:C
^C
for ASCII 03).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
~D
~@D
~:D
~mincol,padchar,commachar,commawidthD
~X
~@X
~:X
~mincol,padchar,commachar,commawidthX
~O
~@O
~:O
~mincol,padchar,commachar,commawidthO
~B
~@B
~:B
~mincol,padchar,commachar,commawidthB
~nR
~n,mincol,padchar,commachar,commawidthR
~@R
~:@R
~:R
~:@R
~P
~@P
y
and ies
.
~:P
~P but jumps 1 argument backward.
~:@P
~@P but jumps 1 argument backward.
commawidth is the number of characters between two comma characters.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
~F
~width,digits,scale,overflowchar,padcharF
~@F
~E
E
ee)
~width,digits,exponentdigits,scale,overflowchar,padchar,exponentcharE
~@E
~G
~width,digits,exponentdigits,scale,overflowchar,padchar,exponentcharG
~@G
~$
~digits,scale,width,padchar$
~@$
~:@$
~:$
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
~%
~n%
~&
~n&
~&
and then n-1 newlines.
~|
~n|
~~
~n~
~
<newline>
~:
<newline>
~@
<newline>
~T
~@T
~colnum,colincT
~?
~@?
~(str~)
string-downcase
).
~:(str~)
string-capitalize
.
~@(str~)
string-capitalize-first
.
~:@(str~)
string-upcase
.
~*
~n*
~:*
~n:*
~@*
~n@*
~[str0~;str1~;...~;strn~]
~n[
~@[
~:[
~;
~:;
~{str~}
~n{
~:{
~@{
~:@{
~^
~n^
~n,m^
~n,m,k^
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
~:A
#f
as an empty list (see below).
~:S
#f
as an empty list (see below).
~<~>
~:^
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These are not necesasrily implemented in Kawa!
~I
~F~@Fi
with passed parameters for
~F
.
~Y
~K
~?.
~!
~_
#\space
character
~n_
#\space
characters.
~nC
integer->char
. n must be a positive decimal number.~:S
#<...>
as strings "#<...>"
so that the format output can always
be processed by read
.
~:A
#<...>
as strings "#<...>"
so that the format output can always
be processed by read
.
~F, ~E, ~G, ~$
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(handler key args ...) |
key may be a symbol. The thunk takes no
arguments. If thunk returns normally, that is the return value of
catch
.
Handler is invoked outside the scope of its own catch
. If
handler again throws to the same key, a new handler from further
up the call chain is invoked.
If the key is #t
, then a throw to any symbol will match
this call to catch
.
If the key is a symbol it will match catches of the same symbol or of #t.
If there is no handler at all, an error is signaled.
misc-error
and a message constructed by
displaying msg and writing args.
This normally prints a stack trace, and brings you back to
the top level, or exits kawa if you are not running interactively.
<java.lang.Throwable>
.
(This is implemented just like Java's try
-finally
.)
var type exp ... |
Once a handler is selected,
the var is bound to the thrown exception, and the exp in
the handler are executed. The result of the try-catch
is the result of body if no exception is thrown, or the
value of the last exp in the selected handler if an
exception is thrown.
(This is implemented just like Java's try
-catch
.)
If the continuation of the dynamic-wind is re-entered (which is not yet possible in Kawa), the in-guard is called again.
This function was added in R5RS.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A location is a place where a value can be stored.
An lvalue is an expression that refers to a location.
(The name "lvalue" refers to the fact that the left operand
of set!
is an lvalue.)
The only kind of lvalue in standard Scheme is a variable.
Kawa also allows computed lvalues. These are procedure
calls used in "lvalue context", such as the left operand of set!
.
You can only use procedures that have an associated setter.
In that case, (set! (f arg ...) value)
is equivalent to ((setter f) value arg ...)
(It is possible the definition will change
to ((setter f) arg ... value)
if Guile goes for that.)
Currently, only a few procedures have associated setter
s,
and only builtin procedures written in Java can have setter
s.
For example:
(set! (car x) 10) |
(set-car! x 10) |
Kawa also gives you access to locations as first-class values:
set!
on the application).
The lvalue can be a local or global variable, or a procedure
call using a procedure that has a setter
.
(define x 100) (define lx (location x)) (set! (lx) (cons 1 2)) ;; set x to (1 . 2) (lx) ;; returns (1 . 2) (define lc (location (car x))) (set! (lc) (+ 10 (lc))) ;; x is now (11 . 2) |
(location variable)
is equivalent to (location lvalue)
.
This works both top-level and inside a function.
Some people might find it helpful to think of a location
as a settable thunk. Others may find it useful to
think of the location
syntax as similar to the C `&' operator;
for the `*' indirection operator, Kawa uses procedure application.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
eval
evaluates expression in the environment indicated
by environment.
The default for environment is the result
of (interaction-environment)
.
The effect of assigning to a variable in this environment (such
as let
) is undefined.
This implementation supports version that is 4 or 5.
The effect of assigning to a variable in this environment (such
as car
) is undefined.
#t
if there is a binding for symbol
in environment; otherwise returns #f
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There is a very preliminary interface to create parallel threads.
The interface is similar to the standard delay
/force
,
where a thread is basically the same as a promise, except that
evaluation may be in parallel.
So far, little or no effort has been made into making Kawa thread-safe. There are no per-thread bindings, and the current input and output parts are global. That needs to change.
force
function has generalized to also work
on threads. If waits for the thread's expression to finish
executing, and returns the result.
10s
).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
<java.lang.Process>
object, using the specified
command and envp.
The command is converted to an array of Java strings
(that is an object that has type <java.lang.String[]>
.
It can be a Scheme vector or list (whose elements should be
Java strings or Scheme strings); a Java array of Java strings;
or a Scheme string. In the latter case, the command is converted
using command-parse
.
The envp is process environment; it should be either
a Java array of Java strings, or the special #!null
value.
make-process
.
"/bin/sh" "-c"
concatenated with the command string;
on non-Unix-systems, it is bound to tokenize-string-to-string-array
.
java.util.StringTokenizer
to parse the command string
into an array of words. This splits the command using spaces
to delimit words; there is no special processing for quotes or other
special characters.
(This is the same as what java.lang.Runtime.exec(String)
does.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(lambda lambda-list form ...)
as the expansion function for name.
When the translator sees an application of name,
the expansion function is called with the rest of the application
as the actual arguments. The resulting object must be a Scheme
source form that is futher processed (it may be repeatedly macro-expanded).
If you define a macro with defmacro
, you (currently) cannot use
the macro in the same compilation as the definition.
This restriction does not apply to macros defined by define-syntax
.
(interaction-environment)
; if not (the default),
a new top-level environment is created.
You can create multiple top-level window that can co-exist. They run in separate threads.
cdr
cells of list reversed in place. Note that if list
was pair, it becomes the last pair of the reversed result.
#t
iff value is an instance of type type.
(Undefined if type is a primitive type, such as <int>
.)
<int>
.
synchronized
statement,
except that it may return a result.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |