ftp.nice.ch/pub/next/tools/frontends/Zen.1.0.N.b.tar.gz#/Zen1.0.dist/ZenManual/ZenMan.rtf

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.