This is ZenMan.rtf in view mode; [Download] [Up]
Zen Reference Manual by mikel evins Copyright 1991 by mikel evins All Rights Reserved About Zen Zen is a dynamic programming environment for the NeXT machine. It supports the NextStep interface, and provides an integrated envionment for program development. The Zen programming language is based upon Scheme. The current version of the Zen evaluator is based on the ELK interpreter, by Oliver Laumann. I will make the source for Zen available when I am satisfied that it is suitable for human consumption. The source for ELK is available by anonymous ftp from cs.orst.edu, or from uunet.uu.net. I can be reached at balor!mikel@apple.com (NeXTMail welcome) or at mikel@apple.com. The Zen application and accompanying materials are Copyright 1991 by mikel evins. They are free for any use, but you may not charge money for them without express written permission of mikel evins. The ELK programming language is Copyright 1987, 1988, 1989 by Nixdorf Computer AG and Teles GmbH, Berlin. The author makes no warranty about the suitability of this software for any purpose. Acknowledgements Zen is a simple programming environment in an early stage of development. Its quick preparation is largely due to the excellence of the NextStep development environment and the ready availability of the fine ELK interpreter. I am grateful to NeXT for NextStep, to Oliver Laumann for ELK, and to Christopher Maeda, who did the port of ELK to the NeXT. Elk Copyright This software is Copyright 1987, 1988, 1989, Nixdorf Computer AG and Teles GmbH, Berlin. This software has been written by Oliver Laumann (me) for TELES Telematic Services, Berlin, in a joint project between TELES and Nixdorf Microprocessor Engineering, Berlin. I would like to thank Claus Bathe of NME Berlin for securing the permission from his management to publish this software, Prof. Dr. Sigram Schindler for providing the work environment for ISOTEXT and Elk, and Carsten Bormann for his support and src/bignum.c and src/alloca.h. Any use of this software is permitted provided that this notice is not removed and that neither Oliver Laumann nor TELES nor Nixdorf are deemed to have made any representations as to the suitability of this software for any purpose nor are held responsible for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. Berlin, July 1, 1989 Oliver Laumann net@TUB.BITNET net@tub.cs.tu-berlin.de net@tub.UUCP Introduction Version 1.0 of Zen is a simple but functional programming environment that includes a Scheme interpreter, a NeXT-style editor, a terminal for communicating with the interpreter, and some support for program execution in a NextStep interface. This initial version is distributed in the hope that people will find such a programming environment attractive. If so, future versions of Zen will include many additional features. Planned enhancements include support for PostScript graphics, generation of stand-alone NextStep applications, and a built-in Interface-Builder-like application construction environment. The remainder of this manual contains two parts. The first is a description of the Zen NextStep environment. The second is documentation provided with ELK, adapted for use with Zen. There are some modifications to the ELK interpreter, made to support the integrated environment, and these are documented in the second section. The Zen Programming Environment The Zen Application Zen is distributed as a file package called Zen.app. This distribution enables Zen to manage its various executables and auxiliary files without requiring the user to pay any attention to them. Zen functions as two processes, one handling the user interface, and one handling evaluation of Scheme expressions. This architecture makes it easy to modify the Scheme evaluator and the interface independently, and provides support for a future enhancement that will add multiple evaluators, each in its own process. Future versions of Zen will also permit users to add their own evaluators to the application. The Zen.app file package includes a directory called `zen', which contains the Scheme evaluator, and two auxiliary directories called `scm' and `lib'. `scm' contains Scheme source files used by Zen when it starts up, and `lib' contains object code files that Zen loads as they are needed. Zen Menus The Zen main menu is a standard NeXT-style menu. Its simplicity reflects the small number of features presently supported in Zen. As more features are added, the main menu will become more complex. Following are the items in the main menu and the submenus. Info... The Info... item brings up the Zen Info window. Windows Arrange in Front This item arranges all Zen windows neatly in a staggered formation together. New Editor This item creates a new Zen editor window, and makes it the key window. Zen editor windows support the normal NextStep text-editing functions, with a little added convenience for Scheme programmers. For example, when you use the left and right arrow keys with the Shift key held down, the text insertion caret skips over Scheme s-expressions. You can also use Zen menu items to select s-expressions and evaluate them, or to evaluate the whole contents of an editor window. Open... This item presents an Open Panel, from which the user can choose a Zen source file to open. Zen source files use the extension `.zen'. The Open item only shows files with the `.zen' extension. These files, however, are really just text files, and can be opened in any text editor. Save This item saves the current contents of the top editor window. If the window has not been saved before, then it creates a new file. Save As... This item presents a Save Panel so that the user can specify a new file in which to save the contents of the top editor window. Listener This item brings the Zen Listener window to the front and makes it the key window. There is only one Zen Listener. If you close it and then choose this item, the same window will reappear, and its contents will be unchanged. The Listener acts as a terminal to Zen's Scheme evaluator process. Miniaturize Window This item replaces the current top window with a miniwindow. Close Window This item closes the top Zen window. Edit Cut This item cuts the currently selected text to the NeXT Pasteboard. Copy This item copies the currently selected text to the NeXT Pasteboard. Paste This item replaces the insertion point in the top Zen window with the contents of the NeXT Pasteboard. Select SExpr This item selects the Scheme s-expression just to the left of the insertion caret in the top Zen editor window. Select All This item selects the entire contents of the top Zen window. Eval Load... This item presents an Open Panel. The user can choose a Zen source file, which Zen will then load into the evaluator's environment. This provides a convenient way of loading Scheme programs into the Zen environment. Eval Selection This item sends the selected text in the top Zen editor window to the Scheme evaluator. The results are printed to the Listener. Eval Window This item sends the entire contents of the top Zen editor window to the Scheme evaluator. The results are printed to the Listener. Reset This item resets the evaluator to its top-level read-eval-print loop. This item is most useful when the evaluator has encountered an error, and the user wishes to simply reset and go on, rather than doing any debugging. Abort This item aborts any currently executing Scheme code, returning to the read-eval-print-loop that was active when the code was called. Hide This item hides all of Zen's windows, except for the miniwindow that was created in the Workspace when Zen was launched. Quit This item exits from Zen. You can achieve the same result by calling the Scheme procedure `exit'. The Zen Evaluator Zen's evaluator in version 1.0 is based on Oliver Laumann's Extension Language Kit, or ELK, Scheme interpreter. This is a very rich Scheme interpreter, based upon the Revised3 Report on the Algorithmic Language Scheme (R3RS), by Jonathan Rees and William Clinger. This reference adapts Oliver Laumann's ELK reference for the version of the language incorporated in Zen. For a more complete discussion of the Scheme language, see R3RS. The Zen application communicates with the evaluator through pipes, passing Scheme source text to the seperate evaluator process, and retrieving the printed form of the results. The interface controls the evaluator by executing Scheme source expressions, and by sending signals to the evaluator process. The Evaluator must be able to handle the signals properly, and so must provide explicit support for the Zen application. Additionally, Zen will soon provide support for manipulation of the user interface from Scheme code through the NextStep Speaker and Listener mechanism. A future release will include a documented protocol for evaluators, so that users can substitute their own evaluators for the standard one. The Scheme Kernel 1.Lambda Expressions, Procedures (lambda formals body) See R3RS (procedure-lambda procedure) Returns a copy of the lambda-expression that created procedure. Example: (define (square x) (* x x)) (procedure-lambda square) ==> (lambda (x)(* x x)) (procedure? obj) See R3RS (primitive? obj) Returns #t if obj is a built-in Scheme primitive, and #f otherwise. (compound? obj) Returns #t if obj is a compound procedure (that is, a procedure created by a lambda expression), and #f otherwise. 2.Local Bindings (let bindings body) (let* bindings body) (letrec bindings body) See R3RS 3.Fluid Binding (fluid-let bindings body) bindings is of the form ((variable1 init1)...). The inits are temporarily assigned to the vriables and the body is executed. The variables must be bound in an enclosing scope. When the body exits normally or by invoking a control point, the old values of the variable are restored. In the latter case, when control returns to the body of the fluid-let by invoking a control point created within the body, the bindings change again to the values they had when the body exited. Example: ((lambda (x) (+ x (fluid-let ((x 3)) x))) 1) ==> 4 (fluid-let ((print-length 2)) (write '(a b c d))) ==> '(a b ...) (define (errset thunk) (call-with-current-continuation (lambda (catch) (fluid-let ((error-handler (lambda msg (catch #f)))) (list (thunk)))))) (errset (lambda () (+ 1 2))) ==> (3) (errset (lambda () (/ 1 0))) ==> #f 4.Definitions (define variable expression) (define (variable formals) body) (define (variable . formals) body) See R3RS Returns a symbol, the identifier that was bound. Definitions may appear anywhere within a local body (e.g. a lambda body or a let). If the expression is omitted then void (the non-printing object) is used. Examples: (define nil #f) (define ((f x) y) (cons x y)) (define (g x) ((f x) 5)) (g 'a) ==> (a . 5) 5.Assignment (set! variable expression) See R3RS Returns the previous value of variable. Example: (define-macro (swap x y) `(set! ,x (set! ,y ,x))) 6.Procedure Application (operator operand ...) See R3RS operator can be a macro (see below). ( apply arg ... args) See R3RS 7.Quotation, Quasiquotation (quote datum) 'datum constant Vectors need not be quoted; a vector evaluates to itself. (quasiquote expression) (unquote expression) (unquote-splicing expression) See R3RS 8.Sequencing (begin expression1 expression2 ...) See R3RS (begin1 expression1 expression2 ...) Identical to begin except that the value of expression1 is returned. 9.Conditionals (if test consequent alternative) (if test consequent) See R3RS. In the first form alternative can be the first of a sequence of expression; an implicit begin is supplied. (case key clause1 clause2 ...) See R3RS. Each clause that does not begin with else can be of the form ((datum1 ...) expression1 expression2 ...) or (datum1 expression1 expression2 ...) (cond test consequent alternative) (and test1 ...) (or test1 ...) See R3RS. 10.Booleans (not obj) (boolean? obj) See R3RS. 11.Iteration (let variable bindings body) ĒNamed letē. See R3RS. (map procedure list1 list2 ...) (for-each procedure list1 list2 ...) See R3RS. for-each returns the empty list. (do initializations test body) See R3RS. 12.Continuations (call-with-current-continuation procedure) See R3RS. (control-point? obj) Returns #t if obj is a control point (a continuation), #f otherwise. (dynamic-wind? thunk thunk thunk) dynamic-wind is a generalization of the unwind-protect facility provided by many Lisp systems. All three arguments are procedures of no arguments. In the normal case, all three thunks are applied in order. The first thunk is also applied when the body (the second thunk) is entered by the application of a control point created within the body (by means of call-with-current-continuation ). Similarly, the third thunk is also applied whenever the body is exited by invocation of a control point created outside the body. Examples: `(dynamic-wind (lambda () #f) (lambda () ,body) (lambda () ,@unwind-forms))) (let ((f (open-input-file "foo"))) (dynamic-wind (lambda () #f) (lambda () do something with f) (lambda () (close-port f)))) 13.Delayed Evaluation (delay expression) (force promise) See R3RS. (promise? obj) Returns #t if obj is a promise, an object returned by the application of delay . Otherwise #f is returned. 14.Equivalence Predicates (eq? obj obj) (eqv? obj obj) (equal? obj obj) See R3RS. 15.Pairs and Lists (cons obj obj) (car pair) (cdr pair) See R3RS. (cxr pair pattern) pattern is either a symbol or a string consisting of a combination of the characters `a' and `d'. It encodes a sequence of car and cdr operations; each `a' denotes the application of car , and each `d' denotes the application of cdr. For example, (cxr p "ada") is equivalent to (cadar p) . (caar pair) ... (cdddr pair) (set-car! pair obj) (set-cdr! pair obj) See R3RS. set-car! and set-cdr! return obj. (make-list obj Returns a list of length k initialized with obj . Examples: (make-list 0 'a) ==> () (make-list 2 (make-list 2 1)) ==> ((1 1) (1 1)) (list obj) (length list) (list-ref list) (list-tail list) (last-pair list) (append list) See R3RS. (append! list) Like append , except that the original arguments are modified (destructive append ). The cdr of each argument is changed to point to the next argument. Examples: (define x '(a b)) (append x '(c d)) ==> (a b c d) x ==> (a b) (append! x '(c d)) ==> (a b c d) x ==> (a b c d) (reverse list) See R3RS. (reverse! list) Destructive reverse. (memq obj list) (memv obj list) (member obj list) (assq obj alist) (assv obj alist) (assoc obj alist) (null? obj) (pair? obj) See R3RS. 16.Numbers (= n1 n2 ...) (< n1 n2 ...) (> n1 n2 ...) (<= n1 n2 ...) (>= n1 n2 ...) See R3RS. (1+ n) (1- n) Returns n plus 1 or n minus 1, respectively. (+ n1 n2 ...) (* n1 n2 ...) (- n1 n2 ...) (/ n1 n2 ...) (zero? n) (positive? n) (negative? n) (odd? n) (even? n) (exact? n) ( inexact? n) (abs n) (quotient n1 n2) (remainder n1 n2) (modulo n1 n2) (gcd n1 n2) (lcm n1 n2) (floor n) (ceiling n) (truncate n) (round n) (sqrt n) (exp n) (log n) (sin n) (cos n) (tan n) (asin n) (acos n) (atan n) (atan n1 n2) (min n1 n2) (max n1 n2) See R3RS. exact? always returns #f; inexact? always returns #t. (random) Returns an integer pseudo-random number in the range from 0 to 231-1. (srandom n) Sets the random number generator to the starting point n . srandom returns n . (number? obj) (complex? obj) (real? obj) (rational? obj) (integer? obj) (number->string number) (number->string number radix) (string->number string) (string->number string radix) See R3RS.. 17.Characters (char->integer char) (integer->char n) (char-upper-case? char) (char-lower-case? char) (char-alphabetic? char) (char-numeric? char) (char-whitespace? char) (char-upcase char) (char-downcase char) (char=? char char) (char<? char char) (char>? char char) (char<=? char char) (char>=? char char) (char-ci=? char char) (char-ci<? char char) (char-ci>? char char) (char-ci<=? char char) (char-ci>=? char char) (char? obj) See R3RS. 18.Strings (string char ...) Returns a string containing the specified characters. Examples: (string) ==> "" (string # a #space # b) ==> "a b" (string? obj) (make-string char) (string-length string) (string-ref string) (string-set! string char) Returns the previous value of element k of the given string. (substring string start end) (string-copy string) (string-append string ) (list->string chars) (string->list string) See R3RS. (string-fill! string char) See R3RS. Returns string . (substring-fill! string start end char) See R3RS. Stores char in every element of string from start (inclusive) to end (exclusive). Returns string. (string=? string1 string2 ) (string<? string1 string2 ) (string>? string1 string2 ) (string<=? string1 string2 ) (string>=? string1 string2 ) (string-ci=? string1 string2 ) (string-ci<? string1 string2 ) (string-ci>? string1 string2 ) (string-ci<=? string1 string2 ) (string-ci>=? string1 string2 ) (substring? string1 string2 ) (substring-ci? string1 string2 ) See R3RS. If string1 is a substring of string2 , these procedures return the starting position of the first occurrence of the substring within string2. Otherwise #f is returned. substring-ci? is the case insensitive version of substring?. Examples: (define s "Hello world")) (substring? "foo" x) ==> #f) (substring? "hello" x) ==> #f) (substring-ci? "hello" x) ==> 0) (substring? "!" x) ==> 11 bfs28li360 19.Vectors (vector? obj) (make-vector k) (make-vector k fill) (vector obj ...) (vector-length vector) (vector-ref vector k) See R3RS. (vector-set! vector k obj) See R3RS. Returns the previous value of element k of the vector. (vector->list vector) (list->vector list) See R3RS. (vector-fill! vector fill) See R3RS. Returns vector . (vector-copy vector) See R3RS. Returns a copy of vector . bfs28li360 20.Symbols (string->symbol string) (symbol>string- symbol) See R3RS. (put symbol key value) (put symbol key) Associates value with key in the property list of the given symbol. key must be a symbol. Returns key. If value is omitted, the property is removed from the symbol's property list. (get symbol key) Returns the value associated with key in the property list of symbol. key must be a symbol. If no value is associated with key in the symbol's property list, #f is returned. Examples: (put 'norway 'capital "Oslo") (put 'norway 'continent "Europe") (get 'norway 'capital) ==> "Oslo" (symbol-plist symbol) Returns a copy of the property list of symbol as an alist . Examples: (put 'norway 'capital "Oslo") (put 'norway 'continent "Europe") (symbol-plist 'norway) ==> ((capital . "Oslo") (continent . "Europe")) (symbol-plist 'foo) ==> () (symbol? obj) See R3RS. (oblist) Returns a list of lists containing all currently interned symbols. Each sublist represents a bucket of the interpreters internal hash array. Examples: (define (apropos what) (let ((ret ())) (do ((tail (oblist) (cdr tail))) ((null? tail)) (do ((l (car tail) (cdr l))) ((null? l)) (if (substring? what (symbol->string (car l))) (set! ret (cons (car l) ret))))) ret)) (apropos "let") ==> (let* let letrec fluid-let) (apropos "make") ==> (make-list make-vector make-string) (apropos "foo") ==> () 21.Environments (the-environment) Returns the current environment. (global-environment) Returns the global environment (the ``root'' environment in which all predefined procedures are bound). (environment->list environment) Returns a list representing the specified environment. The list is a list of frames, each frame is a list of bindings (an alist). The car of the list represents the most recently established environment. The list returned by environment >list can contain cycles. Examples: (let ((x 1) (y 2)) (car (environment->list (the-environment)))) ==> ((y . 2) (x . 1)) ((lambda (foo) (caar (environment->list (the-environment)))) "abc") ==> (foo . "abc") (eq? (car (last-pair (environment->list (the-environment)))) (car (environment->list (global-environment)))) ==> #t (procedure-environment procedure) (promise-environment promise) (control-point-environment control-point) Returns the environment in which the the body of the procedure is evaluated, the environment in which a value for the promise is computed when force is applied to it, or the environment in which the control-point has been created, respectively. (environment? obj) Returns #t if obj is an environment, #f otherwise. bfs28li360 22.Ports and Files Generally, a file name can either be a string or a symbol. If a symbol is given, it is converted into a string by applying symbol >string. A tilde at the beginning of a file name is expanded according to the rules employed by the C-Shell (see csh (1)). (call-with-input-file file procedure) (call-with-output-file file procedure) (input-port? obj) (output-port? obj) (current-input-port) (current-output-port) (with-input-from-file file thunk) See R3RS. (with-output-to-file file thunk) (open-input-file file) (open-output-file file) See R3RS. file can be a string as well as a symbol. (close-port port) See close-input-port and close-output-port in R3RS. (clear-output-port) (clear-output-port output-port) If the argument is omitted, it defaults to the current output port. In case of ``buffered'' output, this procedure is used to discard all characters that have been output to the port but have not yet been sent to the file associated with the port. (flush-output-port) (flush-output-port output-port) If the argument is omitted, it defaults to the current output port. In case of ``buffered'' output, this procedure is used to force all characters that have been output to the port to be printed immediately. This may be necessary to force output that is not terminated with a newline to appear on the terminal. An output port is flushed automatically when it is closed. (clear-input-port) (clear-input-port input-port) If the argument is omitted, it defaults to the current input port. In case of ``buffered'' input, this procedure discards all characters that have already been read from the file associated with the port but have not been processed using read or similar procedures. (port-file-name port) Returns the name of the file associated with port if it is a file port, #f otherwise. (tilde-expand file) If file starts with a tilde, performs tilde expansion as described above and returns the result of the expansion (a string); returns file otherwise. file is a string or a symbol. (file-exists? file) Returns #t if file exists, #f otherwise. file is a string or a symbol; tilde expansion is not performed. bfs28li360 23.Input (read) (read input-port) (read-char) (read-char input-port) (read-string) See R3RS. (read-string input-port) If the argument is omitted, it defaults to the current input port. Returns the rest of the current input line as a string (not including the terminating newline). (unread-char char) (unread-char char input-port) If the second argument is omitted, it defaults to the current input port. Pushes char back on the stream of input characters. It is not an error for char not to be the last character read from the port. The procedure returns char . Examples: (define (peek-char port) (unread-char (read-char port) port)) (eof-object? obj) See R3RS. 24.Output print-length print-depth These variables are defined in the global environment. They control the maximum length (and maximum depth, respectively) of a list or vector that is printed. If one of the variables is not bound to an integer, a default value is taken. The default value for print-length is 1000, and the default value for print-depth is 20. (write obj) (write obj output-port) (display obj) (display obj output-port) (write-char char) (write-char char output-port) (newline) (newline output-port) See If the second argument is omitted, it defaults to the current output port. (print obj) (print obj output-port) See If the second argument is omitted, it defaults to the current output port. Prints obj using write and then prints a newline. print returns void . (format destination format-string obj) Prints the third and the following arguments according to the specifications in the string format-string . Characters from the format string are copied to the output. When a tilde is encountered in the format string, the tilde and the immediately following character are replaced in the output as follows: ~s is replaced by the printed representation of the next obj in the sense of write . ~a is replaced by the printed representation of the next obj in the sense of display . ~~ is replaced by a single tilde. ~% is replaced by a newline. An error is signaled if fewer objs are provided than required by the given format string. If the format string ends in a tilde, the tilde is ignored. If destination is #t, the output is sent to the current output port; if #f is given, the output is returned as a string; otherwise, destination must be an output port. Examples: (format #f "Hello world!") ==> "Hello world" (format #f "~s world!" "Hello") ==> " "Hello " world" (format #f "~a world!" "Hello") ==> "Hello world" (format #f "Hello~a") ==> "Hello!" (define (flat-size s) (fluid-let ((print-length 1000) (print-depth 100)) (string-length (format #f "~a" s)))) (flat-size 1.5) ==> 3 (flat-size '(a b c)) ==> 7 25.String Ports String ports are similar to file ports, except that characters are appended to a string instead of being sent to a file, or taken from a string instead of being read from a file. It is not necessary to close string ports. When an string input port has reached the end of the input string, successive read operations return end-of-file. (open-input-string string) Returns a new string input port initialized with string . Examples: (define p (open-input-string "Hello world!")) (read-char p) ==> # H (read p) ==> ello (read p) ==> world! (read p) ==> end of file (define p (open-input-string "(cons 'a 'b)")) (eval (read p)) ==> (a . b) (open-output-string) Returns a new string output port. (get-output-string string-output-port) Returns the string currently associated with the specified string output port. As a side-effect, the string is reset to zero length. Examples: (define p (open-output-string)) (display '(a b c) p) (get-output-string p) ==> "(a b c)" (get-output-string p) ==> "" (define (flat-size s) (let ((p (open-output-string))) (display s p) (string-length (get-output-string p)))) 26.Loading (load file) (load file environment) Loads a source file or an object file. If the file contains source code, the expressions in the file are read and evaluated. If the file contains object code, the contents of the file is linked together with the running interpreter and with additional libraries that are specified by the variable load-libraries (see below). Object files must end in the suffix ``.o''. load returns void. file can be a string as well as a symbol. If an optional environment is specified, the contents of the file is evaluated in this environment instead of the current environment. Example: (fluid-let ((load-noisily? #t)) (load 'test.scm)) load-path This variable is defined in the global environment. It is bound to a list of directories in which files to be loaded are searched for. Each element of the list (a string or a symbol) is used in turn as a prefix for the file name passed to load until opening succeeds. The initial value of load-path is a list of the three elements ``.'' (i. e. the current directory), ``$(TOP)/scm'', and ``$(TOP)/lib'', where $(TOP) is the top-level directory of the Elk installation. load-noisily? This variable is defined in the global environment. When a file is loaded and the value of load-noisily? is true, the result of the evaluation of each expression is printed. The initial value of load-noisily is #f. load-libraries This variable is defined in the global environment. If load-libraries is bound to a string, its value specifies additional load libraries to be linked together with an object file that is loaded into the interpreter (see load above). Its initial value is ``-lc''. (autoload symbol file) Binds symbol in the current environment (as with define). When symbol is evaluated the first time, file is loaded. The definitions loaded from the file must provide a definition for symbol different from autoload , otherwise an error is signaled. autoload-notify? This variable is defined in the global environment. If the value of autoload-notify? is true, a message is printed whenever evaluation of a symbol triggers autoloading of a file. autoload-notify? is bound to #t initially. bfs28li360 27.Macros (macro formals body) Creates a macro. The syntax is identical to the syntax of lambda expressions. When a macro is called, the actual arguments are bound to the formal arguments of the macro expression in the current environment (they are not evaluated), then the body is evaluated. The result of this evaluation is considered the macro expansion and is evaluated in place of the macro call. (define-macro (variable formals) body) (define-macro (variable . formal) body) Like define , except that macro is used instead of lambda . Examples: (define-macro (++ x) `(set! ,x (1+ ,x))) (define foo 5) foo ==> 5 (++ foo) foo ==> 6 (define-macro (while test . body) `(let loop () (cond (,test ,@body (loop))))) (macro? obj) Returns #t if obj is a macro, #f otherwise. (macro-body macro) Returns a copy of the macro expression which has been evaluated to created the given macro (similar to procedure-lambda ). Examples: (define-macro (++ x) `(set! ,x (1+ ,x))) (macro-body ++) ==> (macro (x) (quasiquote (set! (unquote x) (1+ (unquote x))))) (macro-expand list) If the expression list is a macro call, the macro call is expanded. Examples: (define-macro (++ x) `(set! ,x (1+ ,x))) (macro-expand '(++ foo)) ==> (set! foo (1+ foo)) The following function can be used to expand all macro calls in an expression, i. e. not only at the outermost level: (define (expand form) (if (or (not (pair? form)) (null? form)) form (let ((head (expand (car form))) (args (expand (cdr form))) (result)) (if (and (symbol? head) (bound? head)) (begin (set! result (macro-expand (cons head args))) (if (not (equal? result form)) (expand result) result)) (cons head args))))) 28.Error and Exception Handling error-handler This variable is defined in the global environment. When an error occurs or when the procedure error is invoked and the variable error-handler is bound to a compound procedure (the error handler ), the interpreter invokes this procedure. The error handler is called with an object (either the first argument that has been passed to error or a symbol identifying the primitive procedure that has caused the error), and an error message consisting of a format string and a list of objects suitable to be passed to format . Typically, a user-defined error handler prints the error message and then calls a control point that has been created outside the error handler. If the error handler terminates normally or if error-handler is not bound to a procedure, the error message is printed in a default way, and then a reset is performed. interrupt-handler This variable is defined in the global environment. When an interrupt occurs (typically as a result of typing the interrupt character on the keyboard), and the variable interrupt-handler is bound to a procedure (the interrupt handler ), this procedure is called with no arguments. If interrupt-handler is not bound to a procedure or if the procedure terminates normally, a message is printed, and a reset is performed. Examples: (set! interrupt-handler (lambda () (newline) (backtrace) (reset))) (error obj string obj) Signals an error. The arguments of error are passed to the error-handler . Examples: (define (foo sym) (if (not (symbol? sym)) (error 'foo "argument not a symbol: ~s" sym)) top-level-control-point (reset) Performs a reset by calling the control point to which the variable top-level-control-point is bound in the global environment. The control point is called with the argument #t. If top-level-control-point is not bound to a control point, an error message is printed and the interpreter is terminated. Examples: (if (call-with-current-continuation (lambda (x) (fluid-let ((top-level-control-point x)) do something #f))) (print "Got a reset!")) (exit) Terminates the interpreter. The optional argument n indicates the exit code; it defaults to zero. bfs28li360 29.Garbage Collection (collect) Causes a garbage collection. garbage-collect-notify? This variable is defined in the global environment. If the value of garbage-collect-notify? is true, a message indicating the amount of free memory on the heap and the size of the heap is displayed whenever a garbage collection is performed. garbage-collect-notify? is bound to #t initially. bfs28li360 30.Features (feature? symbol) Returns #t if symbol is a feature, i. e. provide has been called to indicate that the feature symbol is present; #f otherwise. (provide symbol) Indicates that the feature symbol is present. Returns void . (require symbol) (require symbol file) (require symbol file environment) If the feature symbol is not present (i. e. (feature? symbol ) evaluates to #f), file is loaded. A message is displayed prior to loading the file if the value of the global variable autoload-notify? is true. If the feature is still not present after the file has been loaded, an error is signaled. If the file argument is omitted, it defaults to symbol. If an environment argument is supplied, the file is loaded into given environment. if the environment argument is omitted, it defaults to the current environment. bfs28li360 31.Miscellaneous (dump file) Writes a snapshot of the running interpreter to file and returns #f. When file is executed, execution of the interpreter resumes such that the call to dump returns #t (i.e., dump actually returns twice). dump closes all ports except the current input and current output port. (eval list) (eval list environment) Evaluates the expression list in the specified environment. If environment is omitted, the expression is evaluated in the current environment. Examples: (let ((car 1)) (eval 'car (global-environment))) ==> primitive car (define x 1) (define env (let ((x 2)) (the-environment))) (eval 'x) ==> 1 (eval 'x env) ==> 2 (bound? symbol) Returns #t if symbol is bound in the current environment, #f otherwise. (type obj) Returns a symbol indicating the type of obj . Examples: (type 13782343423544) ==> integer (type 1.5e8) ==> real (type (lambda (x y) (cons x y))) ==> compound (type # a) ==> character (type '(a b c)) ==> pair (type ()) ==> null (type (read (open-input-string ""))) ==> end-of-file (void? obj) Returns true if obj is the non-printing object, false otherwise. (command-line-args) Returns the command line arguments of the interpreter's invocation, a list of strings. bfs28li360 32.Incompatibilities with R3RS The following list enumerates the points where the Elk Extension Language does not conform to R3RS. These are language features which could cause a Scheme program to not properly run under Elk, although it does run under a R3RS-conforming implementation. Upper and lower case letters in symbols are always distinguished (i. e. Elk is case-sensitive ), except when the interpreter is compiled with a special compile-time option. Quasiquotation can currently not be used to construct vectors. Rational and complex numbers are not implemented. All numbers are inexact. Radix prefixes (#b, #o, #d, and #x) for real numbers are currently not implemented. Prefixes for exact and inexact constants (#e and #i) are not implemented. exact->inexact and inexact->exact are not implemented. close-input-port and close-output-port do not exist. Use close-port instead; it can be applied to input ports as well as output ports. char-ready? is currently not implemented. transcript-on and transcript-off do not exist. A future version of Zen will enable users to save the Listener to a transcript file. bfs32li0 The OOPS Package 1.Using OOPS The OOPS package provides a minimal set of tools that enables a Scheme programmer to program in an object oriented style. The functionality of OOPS is similar to that of packages like CLOS and SCOOPS, although the current version does not support multiple inheritance. The rest of this memo serves as a reference guide to the OOPS package; the reader is assumed to be familiar with the terminology of object oriented programming. Programs that make use of the OOPS package should include the line (require 'oops) Since this involves autoloading of an object file, it may be desirable to dump Scheme after the OOPS package has been loaded. 2.Defining Classes New classes are defined by means of the define-class macro. The syntax of define-class is (define-class class-name . options ) where class-name is a symbol. options can be of the form (super-class class-name ) where class-name is the name of the super-class (a symbol), or (class-vars . var-specs ) or (instance-vars . var-specs ) to specify the class variables and instance variables of the newly defined class. Each var-spec is either a symbol (the name of the variable) or of the form ( symbol initializer ) Variables for which no initializer has been specified are initialized to the empty list. The initializers for class variables are evaluated immediately; initializers for instance variables are evaluated each time an instance of the newly defined class is created. Evaluation of initializers is performed in a way that the initializer of a variable can reference all variables appearing at the left of the variable being initialized; for instance (define-class foo (class-vars (a 10) (b (* a 2)))) would initialize the class variable b to 20. A class inherits all class variables, instance variables, and methods of its super-class. When a class and its super-class each have an instance variable with the same name, the corresponding var-specs must either both have no initializer or initializers with the same value, otherwise an ``initializer mismatch'' error is signaled by define-class . Each instance of a class has an instance variable named self . The value of self is the instance with respect to which self is evaluated. self can be used by methods as the argument to send (see below) to invoke another method within the current instance. define-class does not have a meaningful return value, instead it has a side-effect on the environment in which it is invoked. pardtx960tx1920tx2880tx3840tx4800tx5760tx6720tx7680tx8640tx9600bli360 3.Creating Instances of a Class The macro make-instance is used to create an instance of a class; it returns the instance as its value. The syntax is (make-instance class . args) where class is the class of which an instance is to be created. Each arg of the form (symbol initializer) where symbol is the name of an instance variable of the class, is used to initialize the specified instance variable in the newly created instance. In this case the initializer supersedes any initializer specified in the call to define-class . Thus it is possible to have instance variables with a default initializer that can be overridden for individual instances. The initializers are evaluated in the current environment. make-instance initializes the newly created instance by invoking the initialize-instance method for the class and all super-classes in super-class to sub-class order. That is, the initialize-instance method of the class specified in the call to make-instance is called after all other initialize-instance methods. The arguments passed to the initialize-instance method of a class are those arguments of the call to make-instance that do not represent an initialization form for an instance variable. These arguments are evaluated in the current environment. It is not required for a class to have an initialize-instance method. Consider the following example: (require 'oops) (define-class c (instance-vars a)) (define-class d (instance-vars (b 10)) (super-class c)) (define-method c (initialize-instance . args) (print (cons 'c args))) (define-method d (initialize-instance . args) (print (cons 'd args))) In this example, evaluation of (define x 99) (define i (make-instance d (a 20) 'foo (b x) x)) would print (c foo 99) (d foo 99) Note that first the initialize-instance method of c is invoked and then that of the class d. The instance variables a and b would be initialized to 20 and 99, respectively. 4.Defining Methods A new method can be defined by means of the define-method macro. The syntax is (define-method class lambda-list . body) where class is the class to which the method is to be added, lambda-list is a list specifying the method's name and formal arguments (having the same syntax as the argument of define define-method simply creates a class-variable with the name of the method, creates a lambda closure using the lambda-list and the body forms, and binds the resulting procedure to the newly-created variable. When a message with the name of the method is sent to an instance of the class, the method is invoked, and the body is evaluated in the scope of the instance (so that it can access all instance and class variables). pardtx960tx1920tx2880tx3840tx4800tx5760tx6720tx7680tx8640tx9600bli360 5.Sending Messages A message can be sent to an instance by means of the function send. The syntax of send is (send instance message . args ) where instance is the instance to which the message is to be sent, method is the name of the method to be invoked (a symbol), and args are the arguments to be passed to the method. Example: (define-class c (instance-vars a) (class-vars (b 10))) (define-method c (foo x) (cons (set! a x) b)) ; set! returns previous value (define i (make-instance c (a 99))) (send i 'foo 1) returns (99 . 10) (send i 'foo 2) returns (1 . 10) When a message is sent to an instance for which no method has been defined, a ``message not understood'' error is signaled. The function send-if-handles is identical to send, except that it returns a list of one element, the return value of the method, or #f when the message is not understood by the instance. pardtx960tx1920tx2880tx3840tx4800tx5760tx6720tx7680tx8640tx9600bli360 6.Evaluating Expressions within an Instance The macro with-instance can be used to evaluate expressions within the scope of an instance. The syntax is (with-instance instance . body ). The body forms are evaluated in the same environment in which a method of instance would be evaluated, i. e. they can access all and class and instance variables (including self). with-instance returns the value of the last body form. Example: (define-class c (class-vars (x 5)) (instance-vars y)) (define i (make-instance c (y 1))) (define x 10) (with-instance i (cons x y)) returns (5 . 1) pardtx1140tx2300tx3440tx4600tx5760tx6900tx8060tx9200tx10360tx11520f1fs28 7.Setting Instance and Class Variables Generally class and instance variables are manipulated by methods or, if applicable, from within a with-instance form. In addition, values can be assigned to class and instance variables without involving a message send by means of the instance-set! macro. The syntax of instance-set! is (instance-set! instance variable value) where variable is a symbol, the name of the class or instance variable. instance-set! returns the previous value of the variable (like set!) Class variables can be modified without involving an instance of the class by means of the macro class-set!. (class-set! class variable value ). variable must be the name of a class variable of class. Note that one difference between (instance-set! i 'var x) and (with-instance i (set! var x)) is that in the former case x is evaluated in the current environment while in the latter case x is evaluated within the scope of the instance (here x might be a class or instance variable). pardtx960tx1920tx2880tx3840tx4800tx5760tx6720tx7680tx8640tx9600bli360 8.Obtaining Information about Classes and Instances The function class-name returns the name of a class (a symbol) or, when applied to an instance, the name of the class of which it is an instance. The predicate method-known? can be used to check whether a method of a given name is known to a class. The syntax is (method-known? method class ) where method is a symbol. The type predicates class? and instance? can be used to check whether an object is a class or an instance, respectively. The functions (check-class symbol object ) check-class and (check-instance symbol object ) check-instance check whether object is a class (i. e. satisfies the predicate class?) or an instance, respectively, and, if not, signal an error; in this case symbol is used as the first argument to error . The functions describe-class and describe-instance print the components (name, class/instance variables, etc.) of a class or instance, respectively. The function describe has been extended in way that when (feature? 'oops) is true, describe-class or describe-instance are called when describe is applied to an object that satisfies class? or instance?, respectively.
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.