Lisp Machine System Release 89 Notes

System 89 comes with microcode 201.  It was first released with microcode 183,
but certain new features work only with 201.

Microcode 183 will work with system 87, and system 87 bands should be updated
to use 183, as it fixes some bugs.

There are no major incompatibilities between systems 87 and 89.

Programming Changes:

[0] The System Functions Are Documented!

Hundreds of documentation strings have been added to the functions in
the system.  Just about every function you might ever think of calling
now has a documentation string, which you can view using the editor
commands C-Shift-D and M-Shift-D.

C-Shift-D prints just the first line of documentation for the function
you are inside a call to; this is like C-Shift-A.

M-Shift-D prints the full documentation for a function, reading its name
(defaulting to the same one C-Shift-D would give you).

C-Shift-D is available in the rubout handler as well as the editor; there it prints
the complete documentation.

ZWEI, ZMAIL, the demos, and the CADR package have yet to be gone over.

Major Incompatibilities in the Not Quite Immediate Future

		[1] Division of Fixnums Will Change Its Meaning:
		[2] New Common Lisp Division Functions:
		[3] (LISTP NIL) will return T, some day.
		[4] Arrays Will Be Stored in Row-Major Order.

Common Lisp will require some incompatible changes to the Lisp machine
system.  None of these changes is happening yet.  But some new functions are
being added now to smooth the way.

[1] Division of Fixnums Will Change Its Meaning:

At some time in the future, ordinary division, the function //, will
behave differently on integer arguments: it will return a rational number
which is the mathematically correct ratio between the arguments.
This is part of the adoption of Common Lisp (and therefore, the same
change will happen at some time in Symbolics systems as well).

If you have code which depends on dividing integers and getting an
integer as the value, you should convert your code now to use TRUNCATE
or one of the other integer division functions.

Meanwhile, the eventual meaning of // is available now under the name %DIV.

The change in // is probably several months in the future, but it is not too
soon to prepare for the change.  When // changes, %DIV and TRUNCATE will not change.

[2] New Common Lisp Division Functions:

(FLOOR x) returns the largest integer not greater than x.
(CEILING x) returns the smallest integer not less than x.
(TRUNCATE x) is (FLOOR x) if x is positive, (CEILING x) if x is negative.
(ROUND x) returns the closest integer to x.
 If x is midway between two integers, the even one is returned.

All four functions return a second value which is the remainder:
 the argument minus the value.

When given two arguments, these functions divide the first by the second
and convert the quotient to an integer.  The second value is
the original dividend, minus the quotient times the divisor.

TRUNCATE is the same as the current meaning of //, when operating on fixnums.

[3] (LISTP NIL) will return T, some day.

This change is another part of adopting Common Lisp.

The new function CONSP is currently the same as LISTP, but when
LISTP is changed, CONSP will not be changed.  You should begin converting
programs now to use CONSP instead of LISTP when appropriate.

[4] Arrays Will Be Stored in Row-Major Order.

At some time in the future, the order in which array elements are stored
internally will change.  This is also part of adopting Common Lisp.

Most programs that use arrays will not be affected by the change.  However, if
you use indirect arrays which are multidimensional, or which indirect to
multidimensional arrays, you will notice the effects.  Programs which move
sequentially through large arrays will continue to work, but the best subscript
order for optimal paging behavior will be the opposite of what it is now.

In addition, the order of pixels in the hardware screen buffer will not
be changed.  So all array references to such arrays -- and to arrays
that are BITBLT'ed into them -- must have their indices in the other order.

To smooth the conversion, two new functions AR-2-REVERSE and AS-2-REVERSE
have been created.  These are accessing functions for two-dimensional arrays,
and are currently the same as AREF and ASET on them.  But when the order of
array elements is changed, these two new functions will begin to interchange the
two subscripts.

The significant fact is that if you replace AREF and ASET with AR-2-REVERSE and
AS-2-REVERSE where you access screen arrays, your code will continue to work
properly now, and will also keep working properly when the system is changed.
You will not even have to recompile then.

To create a bit map array, use MAKE-PIXEL-ARRAY.

(MAKE-PIXEL-ARRAY width height &REST options)

This is currently the same as (MAKE-ARRAY (LIST width height) ...)
but when the order of array dimensions changes, it will do
(MAKE-ARRAY (LIST height width) ...) instead.  In other words,
MAKE-PIXEL-ARRAY will use the width as either the first dimension or the second,
whichever is correct.

PIXEL-ARRAY-WIDTH returns the width of a bit array, and PIXEL-ARRAY-HEIGHT
returns its height.  Again, the width is whichever dimension varies faster
through memory.

Programming Changes:

		   [5] Complex Numbers Are Supported.
		   [6] Rational numbers improved:
		   [7] Wildcard File Operations.
		   [8] New Operations on Pathname Objects
		   [9] New Erasing Operation on Windows.
		   [10] DEFSYSTEM Change.
		   [11] :UNBOUND in DEFVAR.
		   [12] CONTENTS Gets the Contents of a Locative.
		   [13] EQL is = on numbers, EQ on other objects.
		   [14] Using DECLAREs Locally.
		   [15] New Function COMPILE-LAMBDA.
		   [16] New Initialization Lists.
		   [17] You Can Tell If a Macro Definition Has Changed.
		   [18] Making Flavor Instances Print Readably.

[5] Complex Numbers Are Supported.

A complex number can have any kind of number as its real part,
and any kind as its imaginary part.

(REALP x) is T if x is real.
(COMPLEXP x) is T if x is not real.

(COMPLEX r i) creates a complex number with real part r and imaginary part i.

(IMAGPART c) returns the imaginary part of the number c,
 which is zero if c is real.

(REALPART c) returns the real part of the number c,
 which is c if c is real.

(CONJUGATE c) returns the conjugate of the number c,
 which is c if c is real.

(SIGNUM c) returns a number with magnitude 1 and the same phase as c.
 This is 1 for positive reals, -1 for negative reals.
 0 is an exception; (SIGNUM 0) is 0.

(PHASE c) returns the phase of the complex number c.
 It is 0 for positive reals.

(CIS x) returns exp(i*x) where x is real.

Three new array types are defined: ART-COMPLEX, ART-COMPLEX-FLOAT and
ART-COMPLEX-FPS-FLOAT.  Using them reduces garbage collection if you
have an array containing only numbers, some of which are complex.
ART-COMPLEX allows the real and imaginary parts to be anything, while
ART-COMPLEX-FLOAT converts them to flonums when you store into the
array.

ART-COMPLEX-FPS-FLOAT is like ART-COMPLEX-FLOAT, but uses the FPS format
for storing each flonum.  Real and imaginary parts alternate in memory.

[6] Rational numbers improved:

The support for rational numbers is now in closer to its final
Common Lisp form.

You can type in a rational number as numerator \ denominator.
Don't actually put in spaces around the \; they appear in the previous line for
visual clarity.  Rational numbers print out that way, too.

(RATIONALP x) is T if the number x is rational.
Note that integers are considered rationals.

(INTEGERP x) is T if x is an integer.  This is the same as FIXP.

(NUMERATOR x) returns the numerator of the rational number x,
 which is x if x is an integer.

(DENOMINATOR x) returns the denominator of the rational number x,
 which is 1 if x is an integer.

You get a rational number by calling RATIONAL or RATIONALIZE.
These convert floating point numbers to rationals.
(An integer is already a rational).

RATIONAL treats the flonum as an exact mathematical value,
whereas RATIONALIZE returns the simplest fraction which would
convert to the specified flonum.

RATIONALIZE takes a second argument which is the number of bits of
precision desired, or the ratio of the allowed error to the number itself.
It will produce a fraction that accounts for the specified precision
of the argument.  This is useful for arguments that are rational!
It will return another fraction with smaller numerator and denominator
that is close to the argument.

The new function %DIV, with integer arguments, will produce a rational value.
Eventually // will behave like %DIV.

[7] Wildcard File Operations.

The functions DELETEF, UNDELETEF and RENAMEF now accept filenames with
wildcards in them, and operate on multiple files.  They also optionally
query about the files.  They return a list of the files operated on.
One unfortunate byproduct of this change is that they are slower in the
ordinary case of a single file with no querying.  If this is important,
you can instead send a :DELETE, :UNDELETE or :RENAME message to a
pathname object.  This lower-level interface does not provide the new
features but is still fast.

The new function FS:COPY-FILE copies a file.  It takes two filenames
(strings or pathnames).  The first argument may be a string instead.
There are two additional arguments: ERROR-P (default T), and COPY-MODE
which says whether to copy as a text file or a binary file.
Possible values are :CHARACTERS, :BINARY, :ASK (always query the user),
:NEVER-ASK (just guess), or NIL (try to guess, but query the user
if the guess is not reasonably certain).  FS:COPY-FILE also works on pathnames
with wildcards. - Hanson.

[8] New Operations on Pathname Objects

The new pathname operation :WILD-P returns T if the pathname it is sent
to contains any sort of wildcards.

The new pathname operation :WILDCARD-MAP is a mapping operation that loops
over all the files that a pathname with wildcards refers to.  It does so
by doing a :DIRECTORY-LIST first.  It also works on pathnames that don't
have wildcards.  Supply this operation with these arguments:
  operation plistp dir-list-options &REST args...
operation is a function to be called on each file.
 It will receive a pathname or a property list as its first argument,
 and args as remaining arguments.
plistp says whether operation should be given a file property list.
 (This takes extra time when a pathname with no wildcards is used).
 If it is NIL, operation's first arg is just a pathname.
 If it is T, operation's first arg is a property list whose car
 is a pathname and whose cdr is alternating properties and values.
 This is just an element of the directory-list which is obtained.
dir-list-options is passed to FS:DIRECTORY-LIST.  You can use this
 to get deleted files mentioned in the list, for example.

The new pathname operation :UNDELETABLE-P returns T if sent to a pathname
for a file system which supports undeletion.

The new pathname operation :SOURCE-PATHNAME returns the pathname of the
source file corresponding to the pathname you sent the message to.  If you
evaluate, or compile and load, a file whose type is not LISP, then this
will get the correct type for the file you loaded or compiled.

Unix files whose names happen to contain ".LISP" or anything else which
is the same as a standard Lisp machine file type no longer cause problems.
In fact, all the long-standing problems with Unix pathnames should now be gone.

FS:MERGE-PATHNAME-DEFAULTS, with a pathname given as the defaults, now uses
that pathname's components as the defaults.  (This may be what you thought
it already did -- it is what I thought it did).

[9] New Erasing Operation on Windows.

(TV:SHEET-CLEAR-STRING sheet string &OPTIONAL start end)

clears enough space after sheet's cursor to hold string (or the specified portion).

[10] DEFSYSTEM Change.

Two new transformations are defined for DEFSYSTEM, for use with programs
that run in Maclisp as well as on the Lisp machine.

They are :COMPAT-COMPILE, :COMPAT-COMPILE-LOAD, and :COMPAT-COMPILE-LOAD-INIT.

They are the same as the transformations :COMPILE, :COMPILE-LOAD and
:COMPILE-LOAD-INIT except that source files are called LSP instead
of LISP.

[11] :UNBOUND in DEFVAR.

You can now define a variable with DEFVAR and give it a documentation
string without specifying an initial value.  Just use :UNBOUND as the
initial value.  DEFVAR will make no attempt to evaluate :UNBOUND; it
will simply not try to set the variable.

Now there is no excuse whatever for writing a DEFVAR without a
documentation string.

[12] CONTENTS Gets the Contents of a Locative.

Given a locative, you can now use the function CONTENTS to get the contents of
the cell to which the locative points.

CONTENTS is actually the same as CDR, but use of CDR has been called a violation
of abstraction.

(SETF (CONTENTS locative) value) works also.

[13] New Function EQL

EQL is = on numbers, EQ on other objects.

(EQL 1 T) => NIL
(EQL 1 1.0) => T
(EQL 'FOO 'FOO) => T

[14] Using DECLAREs Locally.

DECLAREs can now appear at the front of the body of a PROGN, LET, LET*, PROG,
PROG* or internal LAMBDA, and apply to the entire construct, including the local
variables (if any) bound by that construct.  Example:

  (let (x y)
    (declare (special x))
    ...  ;X is special herein
    )

It now works to define a macro that expands, sometimes or always, into a
DECLARE, and use that macro at the front of a function body to provide a local
declaration.

For example,

(DEFMACRO DS (&REST VARS) `(DECLARE (SPECIAL . ,VARS)))

(DEFUN FOO (A B)
  (DS A B)
  (BAR))

will make A and B special in FOO.

[15] New Function COMPILE-LAMBDA.

(COMPILE-LAMBDA lambda-expression &OPTIONAL name processing-mode)

compiles lambda-expression into a compiled function object which remembers
name as its name, and returns it.  No function spec is defined; it is up to the
caller to store the compiled function object somewhere.

If processing-mode is COMPILER:MICRO-COMPILE, the function is microcompiled
instead.

[16] New Initialization Lists.

SI:FULL-GC-INITIALIZATION-LIST is run at the end of the function SI:FULL-GC.
It is specified by the ADD-INITIALIZATION keyword FULL-GC (in any package).

SI:SITE-OPTION-INITIALIZATION-LIST is run whenever new site tables are
loaded, and also on cold booting.  It is specified by the ADD-INITIALIZATION
keyword SITE-OPTION (in any package).  Initializations put on this list are by
default also executed immediately.

[17] You Can Tell If a Macro Definition Has Changed.

The compiler now records the SXHASH of every macro expanded in each function
you compile.  Compiled macros know the SXHASHes of their original expr
definitions so this can be done for them as well.

The records go under :MACROS-EXPANDED in the function's debugging info alist.
The value associated with this keyword is now a list of either macro names or
lists of the form (macroname macro-sxhash).  (Just a macro name is recorded for a
macro which was compiled in earlier systems and does not know the original
SXHASH).

You can get the appropriate SXHASH for the current definition of a macro with
(COMPILER:EXPR-SXHASH macroname).  By comparing the two, you can tell
whether you must recompile the other function because of a change in the
macro.

If a compiled function is fasloaded and can be seen to have been compiled with
a version of a macro which does not match the current definition, a warning is
printed, giving the name of the losing function and the name of the macro.

[18] Making Flavor Instances Print Readably.

SI:PRINT-READABLY-MIXIN is a convenient way of making a flavor's instances
print in a way that can be read back.

In order for it to work, you must define the :RECONSTRUCTION-INIT-PLIST
operation.  It should return a list of init-options which could be passed to
MAKE-INSTANCE to create the desired new instance at read-in time.
SI:PRINT-READABLY-MIXIN cannot define this for you, because only you know
which instance variables ought to be part of the printed representation.

Example:

(defflavor foo (a car-of-a) (si:print-readably-mixin)
  (:inittable-instance-variables a))

(defmethod (foo :init) (ignore)
  (setq car-of-a (car a)))

(defmethod (foo :reconstruction-init-plist) ()
  `(:a ,a))				;Note that car-of-a is not included.

(make-instance 'foo ':a '(69.)) => #mypackage:foo a (71)

As an additional feature, it becomes possible to fasdump objects containing
such instances.

[] READLINE-TRIM stream eof-option

READLINE-TRIM is line READLINE except that any leading or trailing spaces and
tabs are discarded from the line before the value is returned.

  (READLINE-TRIM args...)

is almost the same as

  (STRING-TRIM '(#\SP #\TAB) (READLINE args...))

the difference being that READLINE-TRIM will return the eof-option on end of file
without trying to trim it.

[] (PROMPT-AND-READ keyword format-string format-arguments...)

The function PROMPT-AND-READ serves to read and return an object after
prompting.  You specify the way to read the object with a keyword, and the way
to prompt with a string and arguments that are passd to FORMAT.

The keyword is one of these: :READ, :NUMBER, :EVAL-READ, :EVAL-READ-OR-END,
:STRING, :STRING-OR-NIL, :PATHNAME.

:READ - the object is read by calling READ.
:NUMBER - the object is read by calling READ in base ten.  If it is not a number,
  the user gets an error message and must rub it out and try over.
:EVAL-READ - the object is read by (EVAL (READ)).
:EVAL-READ-OR-END - the object is read by (EVAL (READ)).  However, the user
 can type the End character instead of an object.  In this case, PROMPT-AND-READ
 returns NIL as the first value, and #\End as the second.
:STRING - the object is read by READLINE, so the value is a string.
:STRING-OR-NIL - the object is read by READLINE-TRIM, except that if
 the resulting string is empty, NIL is returned instead.
:PATHNAME - the object is read by (FS:MERGE-PATHNAME-DEFAULTS (READLINE)).
(:PATHNAME :DEFAULTS defaults-list) - like just :PATHNAME, except that
 defaults-list will be passed to FS:MERGE-PATHNAME-DEFAULTS for use as the
 defaults.  defaults-list must be literally present in the list passed to
 PROMPT-AND-READ.

PROMPT-AND-READ always uses QUERY-IO to do the i/o.  It uses the rubout handler
if the stream supports one, and tells the rubout handler how to reprint the
prompt when that is appropriate.

[] :FILL-POINTER Keyword Argument to MAKE-ARRAY.

A new convenient way to make an array with a fill pointer is to use the
:FILL-POINTER argument to MAKE-ARRAY.  The presence of this argument requests
a leader of length one, and the value of the argument is used to initialize the
leader slot.

  (MAKE-ARRAY 5 ':TYPE ART-STRING ':INITIAL-VALUE #\A ':FILL-POINTER 2)
    => "AA"

[] WITH-STACK-LIST and WITH-STACK-LIST*.

These two new special forms allow you to create and use a list whose memory is
allocated inside the stack.  The list will automatically be reclaimed when the
WITH-STACK-LIST is exited, with no permanent consumption of space; but you
had better have no pointers to the list at that time, for they will become garbled.

A use of WITH-STACK-LIST looks like this:

  (with-stack-list (variable list-elements...)
    body...)

During the execution of body, variable will be bound to the temporary list.
list-elements are used as the elements when the list is constructed.
The stack list can be RPLACA'd but it cannot be RPLACD'd.

WITH-STACK-LIST* is called like WITH-STACK-LIST.  The only difference is that it
constructs the list to have a specified final cdr rather than NIL--just as LIST*
does.

[] The Applyhook.

The applyhook is a new companion to the old EVALHOOK feature.  While the
evalhook is called when the interpreter calls EVAL, the applyhook is called when
EVAL would normally call APPLY.  (Never mind that EVAL does not actually call
APPLY per se; it does something equivalent).

To use the applyhook, call EVALHOOK with a third argument, which is the
applyhook function.  As usual, EVALHOOK will evaluate its first argument; but if
that evaluation would apply a function, the applyhook is called instead.
The second argument to EVALHOOK, if non-NIL, is used as the evalhook function,
which is called if the evaluation would call EVAL recursively.

The applyhook function receives two arguments: the function that EVAL was
about to apply, and the list of arguments the function was going to get.  These
are the same sorts of arguments that APPLY expects.  An applyhook function
which simply passes its arguments to APPLY is the same as no applyhook at all.

When either the applyhook function or the evalhook function is called,
both the applyhook and the evalhook are bound off.

[] New Flavor Feature: :ABSTRACT-FLAVOR

:ABSTRACT-FLAVOR is a new DEFFLAVOR option.  Its purpose is to suppress the
warning that you would normally get from COMPILE-FLAVOR-METHODS if there are
any required flavors, methods or instance variables that are missing.  This allows
you to do COMPILE-FLAVOR-METHODS on a flavor which is not actually suited for
instantiation.  (This is useful if the combined methods of this flavor could be
inherited without change by several other flavors which can be instantiated).

Since :ABSTRACT-FLAVOR is intended for flavors that are not suitable for
instantiation, it also marks the flavor so that you are not allowed to try to
instantiate it.  This is not logically necessary, but otherwise, once the
COMPILE-FLAVOR-METHODS had been done with its warning suppressed, you would
be able to instantiate the flavor with never any warning about the missing
required flavors, methods or instance variables.

[]:CASE Method Combination

:CASE is a new type of method combination for flavor methods.

Recall that each type of method combination is a way of taking the various
methods for a given flavor and operation and deciding what order to call them
in, and how.  :DAEMON method combination, which looks for :BEFORE and :AFTER
methods, is just the default method combination type, not the only one.

:CASE method combination provides an automatic subdispatch on the first
argument to the operation.  Each method says which first argument it wants to
handle.  When a message is sent, only one method is called, according to the
first argument in the message.

For example,

  (defflavor foo (a b) ()
    (:method-combination :case :base-flavor-last :do-something))

  (defflavor bar (c) (foo))

  (defmethod (foo :case :do-something :print-a) ()
    (print a))

  (defmethod (foo :case :do-something :clear-b) ()
    (setq b nil))

  (defmethod (bar :case :do-something :set-c) (new-c)
    (setq c new-c))

defines a :DO-SOMETHING operation which, for flavor FOO, understands only
:PRINT-A as its first argument, but for flavor BAR understands either :PRINT-A or
:SET-C.  :PRINT-A and :SET-C are called suboperations.  Each flavor can define
any number of :CASE methods for the same operation if they are for different
suboperations.

You would use this operation in this manner:

  (send my-bar ':do-something ':set-c 'new-value-for-c)

The internals of :CASE method combination would automatically dispatch to the
(BAR :CASE :DO-SOMETHING :SET-C) method to handle this.  Note that you do not
specify any argument variable in the DEFMETHOD to correspond to the :SET-C.

In addition to the :CASE methods, you can also have a primary method.  It gets
called if none of the :CASE methods applies; that is, when the suboperation
does not match any of the:CASE methods.  It is a sort of default handler.  It does
receive the suboperation explicitly as an argument.

You can also have one or more :OR methods.  These are called just before the
primary method, after determining that no :CASE method applies.  If an :OR
method returns non-NIL, that is the end: its first value is the value of the
operation.  If all the :OR methods return NIL, the primary method is used.

The suboperations :WHICH-OPERATIONS, :SEND-IF-HANDLES,
:OPERATION-HANDLED-P, :GET-HANDLER-FOR and :CASE-DOCUMENTATION are
handled specially and automatically.  The first four have meanings analogous to
the operations of the same name.  Note that they consider a suboperation to be
handled only if there is a :CASE method for it.  :CASE-DOCUMENTATION takes one
argument, a suboperation, and returns the documentation string of the :CASE
method for that suboperation, otherwise NIL.

[] (STRING-CAPITALIZE-WORDS string &optional (copy-flag t))

This function performs two transformations on string: it changes all dashes into
spaces, and capitalizes each word.  The initial becomes upper case, and the rest
of each word lower case.

The original string is unchanged, and the value is a new string, unless copy-flag
is nil.

[] Restrictions Lifted on UNWIND-PROTECT and Peculiar Multiple-Value Constructs

UNWIND-PROTECT now interacts correctly with GO and RETURN in all cases.  For
example,

  (prog ()
    (unwind-protect
      (print (if a b (go tag)) stream)
      (close stream))
   tag
    ...)

will now close the stream even if the GO takes place.

RETURN of multiple values to internal destinations now works also.  For example,

  (multiple-value (a b)
    (prog ()
      (print (if c d (return base t)))
      (return ibase nil)))

will set A and B properly, and no longer crash the machine.

These two improvements are often useful together, as in

  (multiple-value (a b)
    (prog ()
      (unwind-protect
	(.... (return x y) ...)
	(close stream))))

[] :NEW-SUGGESTED-NAME and :NEW-SUGGESTED-DIRECTORY Pathname Operations.

The :NEW-SUGGESTED-DIRECTORY operation is nearly the same as the
:NEW-DIRECTORY operation, but it has a slightly different purpose.  The new
directory name is not precisely what is desired, but just a suggestion, based on
some sort of default.  For example, it might be a user name.  Similarly,
:NEW-SUGGESTED-NAME supplies a suggestion for the name, rather than a precise
desired name.  It might be the name of an editor buffer.

The difference between the actions of the new operations and the actions of
:NEW-NAME and :NEW-DIRECTORY is that the new operations may make
file-system-dependent changes in their arguments.  For example, on systems
such as Twenex, where filenames can contain lowercase characters but normally
do not, the -SUGGESTED- operations convert the name to upper case.

[] (DUMP-FORMS-TO-FILE filename forms-list &optional attribute-list)

DUMP-FORMS-TO-FILE writes a QFASL file whose effect, when loaded, is to
execute the forms in forms-list.  For example,

  (dump-forms-to-file "foo" '((setq x 1) (setq y 2)))
  (load "foo")
  x => 1
  y => 2

attribute-list is a file attribute list to give to the QFASL file.  It is a list of
alternating keywords and values, and corresponds to the -*- line of a source file.
The most useful keyword in this context is :PACKAGE, whose value in the
attribute list specifies the package to be used both in dumping the forms and in
loading the file.  If no :PACKAGE keyword is present, the file will be loaded in
whatever package is current at the time.


User Interface Changes:

	    [A] New Convenient Repetition Construct, #`.
	    [B] DIRED Is Now a File System Editor.
	    [C] Unlimited Undo Capability in the Editor.
	    [D] Editor Buffer Sectionization.
	    [E] Kill or Save Buffers.
	    [F] Accessing Editor Buffers as Files.
	    [G] Editing Multi-Font Files.
	    [H] QSEND, REPLY, and MAIL.
	    [I] Network O in SUPDUP and TELNET toggles overprinting.
	    [J] If You Can't See the Bottom of the Screen...
	    [K] Patches Record Original Source File.
	    [L] Terminal Resume command.
	    [M] Directory Maintenance.
	    [N] Local File System Improvements.
	    [O] File Already Exists error handled better.
	    [P] ZMAIL Terminology Changes.
	    [Q] New Hardcopy Functions.
	    [R] Overriding Site Options on a Per-Machine Basis.
	    [S] Recompiling Site Files.
	    [T] Turning Off Read-Onliness of Editor Buffers.
	    [U] Advice and Other Encapsulations May Be Compiled.
	    [V] M-X Rename File Offers to Rename Editor Buffers
	    [W] Period Is Now a Word Delimiter.
	    [Z] ZWEI:*MAJOR-MODE-TRANSLATIONS*

[A] New Convenient Repetition Construct, #`.

#` is a construct for repeating an expression with some
subexpressions varying.  It is an abbreviation for writing several
similar expressions, or for the use of MAPC.  Each subexpression
that is to be varied is written as a comma followed by a list of the
things to substitute.  The expression is expanded at read time into
a PROGN containing the individual versions.

   #`(send stream ',(:clear-input :clear-output))

expands into

   (progn (send stream ':clear-input) (send stream ':clear-output))

Multiple repetitions can be done in parallel by using commas
in several subexpressions:

   #`(renamef ,("foo" "bar") ,("ofoo" "obar"))

expands into

   (progn (renamef "foo" "ofoo")
	  (renamef "bar" "obar"))

If you want to do multiple independent repetitions, you must use nested
#` constructs.  Individual commas inside the inner #` apply to
that #`; they vary at maximum speed.  To specify a subexpression
that varies in the outer #`, use two commas.

   #`#`(print (* ,(5 7) ,,(11. 13.)))

expands into

   (progn (progn (print (* 5 11.)) (print (* 7 11.)))
	  (progn (print (* 5 13.)) (print (* 7 13.)))

[B] DIRED Is Now a File System Editor.

DIRED now has several new and changed commands, giving it the full power
of the Symbolics File System Editor.

First of all, the C command now copies the file on the line you are pointing at.
The name to copy to is read with a minibuffer.  The command for comparing
the file against its most recent version is now called =.

Click right on the mouse now gets a menu of operations on the file
the mouse was pointing to.  All the usual operations are available this way.

One new command is S, for Subdirectory.  If you are pointing to a line
which describes a subdirectory, this command inserts a listing of that
subdirectory into the DIRED buffer underneath the subdirectory itself.
Thus, you can operate on multiple levels of directory at once.
Using S again removes the subdirectory's files from the display.
Indentation is used to show you which files are in subdirectories.

The X command in DIRED is no longer the same as Meta-X.  Instead, it is like Q
but does not exit.  That is, it processes all the deletions, printing and
function applications you have specified, but leaves you in DIRED.

Meanwhile, processing the files with X or Q now eliminates all F, P and A
(Find File, Print or Apply Function) markings found on files, so you get a
clean slate to request a new set of operations.  D markings are left on
the deleted files, since they are now deleted; but if you expunge, or
if the file system does not support undeletion, the deleted files are
removed from the Dired buffer entirely.

Sorting is now done using M-X commands.
The sorting commands are M-X Sort Increasing Creation Date,
M-X Sort Increasing Reference Date, M-X Sort Increasing Size,
and M-X Sort Increasing File Name.

There are also four other commands with Decreasing instead of Increasing.

If you would like any file operation that you do not see in the Help printout of
DIRED, please request it.

Meanwhile, the commands M-X Delete File, M-X Undelete File,
M-X Rename File and M-X Copy File now accept filenames with wildcards
and operate on multiple files.

[C] Unlimited Undo Capability in the Editor.

The editor now saves all the changes you make to each buffer,
and you can undo them as far back as you like by doing M-X Undo
multiple times.  To undo the undoing, use M-X Redo.  These commands
also show you a summary of the part of the buffer they are going to change
and what it will be changed to, and then they ask for confirmation.

Since these commands may be useful more often, they are now on
the keys C-Shift-U and C-Shift-R.   When you use those keys, there is no
querying for confirmation.  You simply see the result.

If the variable ZWEI:*UNDO-SAVE-SMALL-CHANGES* is non-NIL,
absolutely all editing operations are saved.  Even individual insertions
and deletions are saved, but batched together.
This mode is now the default as of 89.26.

The undo memory for a buffer is cleared out when you read or write a file
with that buffer.

[D] Editor Buffer Sectionization.

M-X Compile Buffer Changed Sections, etc., now can always tell when new
functions have been inserted in the buffer.  When it says that it is
compiling function FOO, you can trust that this means precisely function
FOO and no other.

It is still the case that inserting a function causes the following
function to be marked as changed.  So Compile Buffer Changed Sections
will tell you it is recompiling the following function as well as
compiling the inserted function.  This is not easy to fix.

[E] Kill or Save Buffers.

M-X Kill or Save Buffers allows you to kill and save the same file.

[F] Accessing Editor Buffers as Files.

Three new host names, ED:, ED-BUFFER:, and ED-FILE: are available for opening
editor buffers as if they were files.  ED: uses the completing reader to recognise
abbreviated buffer names.  ED-BUFFER: requires the exact name.  ED-FILE: takes a
file name and looks for a buffer by that name, if necessary creating a new buffer
visiting the file.  --Devon

[G] Editing Multi-Font Files.

* is now understood in multi-font files being read into ZWEI.

When multi-font files are saved,  is used when appropriate to say that
the font has changed back to one that was in use before.

As a result, if you use a text justifier such as R or BOLIO in which
pecifies a font change, you can now have your files displayed in your
favorite "equivalent" Lisp machine fonts when you edit it.

[H] QSEND, REPLY, and MAIL.

The function QSEND now accepts multiple recipient names.
The names go in one string, separated by commas, as in
(QSEND "RMS@OZ, FOO@OZ" "Message").
The value is a list of the recipients to which the message was successfully sent.

You can also send a message to multiple people in Converse, just by putting
multiple names in the To: line of the message.

The function REPLY sends a message to the person who last sent you one.
It normally takes one argument, the message.

In either QSEND or REPLY, if you do not specify the message as an argument, it is
read from STANDARD-INPUT.  While you are typing the message, you can type the
command Control-Meta-E to switch to Converse.  The text you had entered, and
the recipient, will be provided there for you.  In REPLY, you can also type
Control-Meta-Y, which will insert the contents of the message you are replying
to.

The function MAIL, when given two arguments (recipient and message),
no longer enters the editor.  It sends the string as you gave it.

These features were added by HDT.

[I] Network O in SUPDUP and TELNET Toggles Overprinting.

Normally, SUPDUP and TELNET overprint if the remote system sends
two characters to be output on the same spot without erasing.
If you are talking to a system that assumes your terminal cannot
overprint, this may look ugly.  Network O causes SUPDUP or TELNET
to erase character positions when they are about to be written in,
so that your screen will look right.

[J] If You Can't See the Bottom of the Screen...

TV:SET-TV-SPEED now takes a second optional argument which specifies
how many scan lines at the bottom of the screen should be unused.
This is useful if it is hard to see some of the bottom of the screen
because it is hidden behind a cover.

If you do not have any preference for the first argument, use 60.5, which is the
default.

[K] Patches Record Original Source File.

Patches record the original source file of the contents of the patch, so that if the
patch defines any new functions, the editor will find their definitions in their
actual source files rather than in the patch file.

[L] The Terminal Resume Command.

When you are notified that a deexposed window is waiting to type out,
you can type Terminal Resume to permit it to typeout while remaining deexposed.
It used to be necessary to select the window in order to do this.

[M] Directory Maintenance.

(FS:BALANCE-DIRECTORIES dirspec1 dirspec2 &REST options)

Generates directory lists using the dirspec arguments, then analyzes
the lists to determine which files appear in one directory and not the
other; any files that aren't up to date in either directory are
copied.  The result is that each directory contains up to date copies
of every file in either directory.

A number of options are available for controlling the actions of the
program.  Note that dirspec may be anything that is acceptable to
FS:DIRECTORY-LIST, so it is possible to balance selected parts of a
directory.  - Hanson.

[N] Local File System Improvements.

Subdirectories are now allowed.
Subdirectories appear in a pathname separated by periods, before the semicolon:
	     LM: RMS.SUBDIR.LEVEL2; FOO.BAR#>

Also, Twenex-style pathname syntax is now allowed for the local file
system as an alternative to the old syntax.  Simply use whichever syntax
you prefer.

	     LM: <RMS.SUBDIR.LEVEL2>FOO.BAR.0

If the flag FS:*LMFS-USE-TWENEX-SYNTAX* is set to non-NIL, pathnames
for local files will print out in Twenex syntax, rather than the
normal ITS-like syntax.  It is always possible to type them in using
either syntax.

Note that changing the flag's value will not change the printed
representation of an existing pathname object, since it is cached.
Setting this flag in your login init file will eliminate most such
confusion.

[O] "File Already Exists" Error Handled Better.

If you compile a file on a Twenex that has already been compiled, Twenex
will give a "File already exists" error because a QFASL file of the same
version was created by the previous compilation.

The Lisp machine will now offer to delete the old QFASL file for you.
You can type Y, N or P.  If you type N, you get the usual "use what
filename instead" offer.  P is the same as Y for this question and all
such questions in the future.  It sets the following variable to T:

FS:*AUTO-DELETE-EXISTING-FILE*
 If non-NIL, an attempt to write a file with a specific version number
that already exists will try to delete the old file immediately.
Initially NIL.

Note: if someone is reading the file, Twenex will not allow it to be
deleted or renamed.  There is absolutely no way on Twenex to implement
what is supposed to be the default mode of opening an output file: if a
file with the specified name and version already exists, to
replace it when the new file is closed.  Doesn't Twenex suck?

[P] ZMAIL Terminology Changes.

There has been a change in terminology in ZMAIL.  What used to be called
a "mail file" is now called a "buffer".  "Temporary mail files" are now
"temporary buffers", or "subset buffers" if they are made with a filter
(yielding the set of all messages in a universe that satisfy the filter).
"Disk mail files" are now "mail file buffers".  The term "mail file" is
still used, but now always refers to an actual file rather than an
entity within ZMAIL.

[Q] New Hardcopy Functions.

There are some new printer-independent functions for making hardcopy output.
Each type of printer is named with a keyword; you specify a printer with either
a printer-type keyword by itself, or with a list containing a printer-type keyword
and arguments.  The purpose of the arguments is to specify a particular printer
of that type, if there can be more than one.  Some printer-types want arguments
and some do not.

For example, :DOVER is a printer type that does not take arguments -- there is no
provision for more than one Dover.  So the printer you would specify is just the
keyword :DOVER.

Another type of "printer" is :PRESS-FILE, which means that the "printing" is done
by writing a press format file on a file server.  This type of printer does require
an argument, with which you specify the name to give the press file.  So,
(:PRESS-FILE "<RMS>FOO.PRESS") is an example of a possible printer of type
:PRESS-FILE.

(HARDCOPY-FILE filename &REST options)

prints the file filename according to options (a list of alternating keywords and values).
Options include :PRINTER, whose value specifies the printer to use, and
:FORMAT, whose value is either :TEXT, :PRESS, :XGP or :SUDS-PLOT, which
specifies how to interpret the contents of the file (this defaults from the
filetype).  Individual printers can implement other formats, and may fail to
implement all of these.

Each type of printer may implement other options.  See the on-line
documentation of HARDCOPY-FILE for more information.

To find out whether your output has been printed, use

(HARDCOPY-STATUS &OPTIONAL printer stream)

which prints the status of the specified or default printer, if that makes sense.
It will generally describe both the printer itself and the spooler queue if there is
one.  It is not implemented for all printers (for example, it is not meaningful for
printers of type :PRESS-FILE).

To print out the contents of an array, such as the screen, as black and white
dots, use the function

(HARDCOPY-BIT-ARRAY array left top right bottom &REST options)

The first argument is the array to print, and the next four specify the
subrectangle to use.  All four measure from the top left corner, which is
element 0, 0 of the array.  options can include :PRINTER.

The default printer to use for HARDCOPY-FILE and HARDCOPY-STATUS is the value
of SI:*DEFAULT-PRINTER*.  For HARDCOPY-BIT-ARRAY, the default is the value of
SI:*DEFAULT-BIT-ARRAY-PRINTER*.  The separate default is because not all
printers can print a full screen bit array.

These two variables are initialized from the site options :DEFAULT-PRINTER and
:DEFAULT-BIT-ARRAY-PRINTER.  They can also be specified on a per-machine
basis in the LMLOCS file, as follows.

[R] Overriding Site Options on a Per-Machine Basis.

The file SYS: SITE; LMLOCS LISP, which describes the location of each
Lisp machine at your site, can now contain a list of site options which
should be overridden for that particular machine.

The entry for a machine can now have six elements.  The sixth element is
a list of site option specifications, each of the form

   (site-option-name expression)

This is just like what would go in the SITE file for that option.

For example, it might be useful to specify the :DEFAULT-PRINTER option
separately for individual machines, so each machine can print on a
printer near it.

The function GET-SITE-OPTION checks the per-machine specifications
before the site definition, so no other code should need to be changed.

A new initialization list, SI:SITE-OPTION-INITIALIZATION-LIST, is run at
an appropriate time when new site files are loaded and also after
booting.  It is useful for reinitializing anything that depends on a
site option.  The ADD-INITIALIZATION keyword SITE-OPTION specifies this list.

[S] Recompiling Site Files.

There is now an easy way to recompile the site files, including the host
table.  Just do (MAKE-SYSTEM 'SITE 'COMPILE).

[T] Turning Off Read-Onliness of Editor Buffers.

The new command C-X C-Q toggles the read-only flag of the selected
editor buffer.

[U] Advice and Other Encapsulations May Be Compiled.

Recall that ADVISE, TRACE and BREAKON work by putting what are called
encapsulations on a function, and these are actually separate functions (lambda
expressions) which refer to the original function.  You can now cause these
functions to be compiled.  As a result, it becomes practical to use advice
in places that are called frequently.

(COMPILE-ENCAPSULATIONS function-spec &REST encapsulation-types)

compiles the specified types of encapsulations of function-spec.  Standard types
of encapsulations include ADVISE, TRACE and BREAKON, and also SI:RENAME-WITHIN
(a kind of encapsulation that is put on the function FOO if you advise, trace or
breakon (:WITHIN FOO BAR) for any function BAR called by FOO).

If you don't specify any types of encapsulations, all encapsulations that
function-spec has are compiled.

If you redefine one of the encapsulations -- for example, if you add additional
advice -- then that encapsulation is no longer compiled.  However, redefining
the function itself does not cause encapsulations to be uncompiled.

If the variable COMPILE-ENCAPSULATIONS-FLAG is non-NIL, all encapsulations that
you create or alter are compiled automatically.

[V] M-X Rename File Offers to Rename Editor Buffers

If you rename with M-X Rename File a file that is being edited, it offers to
rename the editor buffer as well.

[W] Period Is Now a Word Delimiter.

Except in MIDAS mode, the character Period is now a word delimiter in the editor.

[Z] ZWEI:*MAJOR-MODE-TRANSLATIONS*

If you frequently edit files whose attribute lists specify modes which do not exist
in ZWEI, you can "translate" those modes to other modes which do exist.
Push an element of the form (file-mode . translated-mode) onto the variable
ZWEI:*MAJOR-MODE-TRANSLATIONS*, and files which specify mode file-mode will
be edited in mode translated-mode.  Both modes should be keywords, and should
not contain the word MODE.

Initially, this variable has one element: (:SCRIBE . :TEXT)

[] COMPILER:COMPILER-VERBOSE

If this variable is non-NIL the compiler prints a message at the beginning of
each function it compiles, stating the function's name.
    

Last modified: 2025/06/05 09:05:21 (UTC) by ams