diff options
Diffstat (limited to 'slib.info-4')
-rw-r--r-- | slib.info-4 | 1248 |
1 files changed, 0 insertions, 1248 deletions
diff --git a/slib.info-4 b/slib.info-4 deleted file mode 100644 index 3d3da19..0000000 --- a/slib.info-4 +++ /dev/null @@ -1,1248 +0,0 @@ -This is Info file slib.info, produced by Makeinfo-1.64 from the input -file slib.texi. - - This file documents SLIB, the portable Scheme library. - - Copyright (C) 1993 Todd R. Eigenschink Copyright (C) 1993, 1994, 1995 -Aubrey Jaffer - - Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - - Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - - Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be stated in a -translation approved by the author. - - -File: slib.info, Node: Syntactic Closures, Next: Syntax-Case Macros, Prev: Macros That Work, Up: Macros - -Syntactic Closures -================== - - `(require 'syntactic-closures)' - - - Function: macro:expand EXPRESSION - - Function: synclo:expand EXPRESSION - Returns scheme code with the macros and derived expression types of - EXPRESSION expanded to primitive expression types. - - - Function: macro:eval EXPRESSION - - Function: synclo:eval EXPRESSION - `macro:eval' returns the value of EXPRESSION in the current top - level environment. EXPRESSION can contain macro definitions. - Side effects of EXPRESSION will affect the top level environment. - - - Procedure: macro:load FILENAME - - Procedure: synclo:load FILENAME - FILENAME should be a string. If filename names an existing file, - the `macro:load' procedure reads Scheme source code expressions and - definitions from the file and evaluates them sequentially. These - source code expressions and definitions may contain macro - definitions. The `macro:load' procedure does not affect the - values returned by `current-input-port' and `current-output-port'. - -Syntactic Closure Macro Facility --------------------------------- - - A Syntactic Closures Macro Facility - - by Chris Hanson - - 9 November 1991 - - This document describes "syntactic closures", a low-level macro -facility for the Scheme programming language. The facility is an -alternative to the low-level macro facility described in the `Revised^4 -Report on Scheme.' This document is an addendum to that report. - - The syntactic closures facility extends the BNF rule for TRANSFORMER -SPEC to allow a new keyword that introduces a low-level macro -transformer: - TRANSFORMER SPEC := (transformer EXPRESSION) - - Additionally, the following procedures are added: - make-syntactic-closure - capture-syntactic-environment - identifier? - identifier=? - - The description of the facility is divided into three parts. The -first part defines basic terminology. The second part describes how -macro transformers are defined. The third part describes the use of -"identifiers", which extend the syntactic closure mechanism to be -compatible with `syntax-rules'. - -Terminology -........... - - This section defines the concepts and data types used by the syntactic -closures facility. - - "Forms" are the syntactic entities out of which programs are - recursively constructed. A form is any expression, any - definition, any syntactic keyword, or any syntactic closure. The - variable name that appears in a `set!' special form is also a - form. Examples of forms: - 17 - #t - car - (+ x 4) - (lambda (x) x) - (define pi 3.14159) - if - define - - An "alias" is an alternate name for a given symbol. It can appear - anywhere in a form that the symbol could be used, and when quoted - it is replaced by the symbol; however, it does not satisfy the - predicate `symbol?'. Macro transformers rarely distinguish - symbols from aliases, referring to both as identifiers. - - A "syntactic" environment maps identifiers to their meanings. - More precisely, it determines whether an identifier is a syntactic - keyword or a variable. If it is a keyword, the meaning is an - interpretation for the form in which that keyword appears. If it - is a variable, the meaning identifies which binding of that - variable is referenced. In short, syntactic environments contain - all of the contextual information necessary for interpreting the - meaning of a particular form. - - A "syntactic closure" consists of a form, a syntactic environment, - and a list of identifiers. All identifiers in the form take their - meaning from the syntactic environment, except those in the given - list. The identifiers in the list are to have their meanings - determined later. A syntactic closure may be used in any context - in which its form could have been used. Since a syntactic closure - is also a form, it may not be used in contexts where a form would - be illegal. For example, a form may not appear as a clause in the - cond special form. A syntactic closure appearing in a quoted - structure is replaced by its form. - -Transformer Definition -...................... - - This section describes the `transformer' special form and the -procedures `make-syntactic-closure' and `capture-syntactic-environment'. - - - Syntax: transformer EXPRESSION - Syntax: It is an error if this syntax occurs except as a - TRANSFORMER SPEC. - - Semantics: The EXPRESSION is evaluated in the standard transformer - environment to yield a macro transformer as described below. This - macro transformer is bound to a macro keyword by the special form - in which the `transformer' expression appears (for example, - `let-syntax'). - - A "macro transformer" is a procedure that takes two arguments, a - form and a syntactic environment, and returns a new form. The - first argument, the "input form", is the form in which the macro - keyword occurred. The second argument, the "usage environment", - is the syntactic environment in which the input form occurred. - The result of the transformer, the "output form", is automatically - closed in the "transformer environment", which is the syntactic - environment in which the `transformer' expression occurred. - - For example, here is a definition of a push macro using - `syntax-rules': - (define-syntax push - (syntax-rules () - ((push item list) - (set! list (cons item list))))) - - Here is an equivalent definition using `transformer': - (define-syntax push - (transformer - (lambda (exp env) - (let ((item - (make-syntactic-closure env '() (cadr exp))) - (list - (make-syntactic-closure env '() (caddr exp)))) - `(set! ,list (cons ,item ,list)))))) - - In this example, the identifiers `set!' and `cons' are closed in - the transformer environment, and thus will not be affected by the - meanings of those identifiers in the usage environment `env'. - - Some macros may be non-hygienic by design. For example, the - following defines a loop macro that implicitly binds `exit' to an - escape procedure. The binding of `exit' is intended to capture - free references to `exit' in the body of the loop, so `exit' must - be left free when the body is closed: - (define-syntax loop - (transformer - (lambda (exp env) - (let ((body (cdr exp))) - `(call-with-current-continuation - (lambda (exit) - (let f () - ,@(map (lambda (exp) - (make-syntactic-closure env '(exit) - exp)) - body) - (f)))))))) - - To assign meanings to the identifiers in a form, use - `make-syntactic-closure' to close the form in a syntactic - environment. - - - Function: make-syntactic-closure ENVIRONMENT FREE-NAMES FORM - ENVIRONMENT must be a syntactic environment, FREE-NAMES must be a - list of identifiers, and FORM must be a form. - `make-syntactic-closure' constructs and returns a syntactic closure - of FORM in ENVIRONMENT, which can be used anywhere that FORM could - have been used. All the identifiers used in FORM, except those - explicitly excepted by FREE-NAMES, obtain their meanings from - ENVIRONMENT. - - Here is an example where FREE-NAMES is something other than the - empty list. It is instructive to compare the use of FREE-NAMES in - this example with its use in the `loop' example above: the examples - are similar except for the source of the identifier being left - free. - (define-syntax let1 - (transformer - (lambda (exp env) - (let ((id (cadr exp)) - (init (caddr exp)) - (exp (cadddr exp))) - `((lambda (,id) - ,(make-syntactic-closure env (list id) exp)) - ,(make-syntactic-closure env '() init)))))) - - `let1' is a simplified version of `let' that only binds a single - identifier, and whose body consists of a single expression. When - the body expression is syntactically closed in its original - syntactic environment, the identifier that is to be bound by - `let1' must be left free, so that it can be properly captured by - the `lambda' in the output form. - - To obtain a syntactic environment other than the usage - environment, use `capture-syntactic-environment'. - - - Function: capture-syntactic-environment PROCEDURE - `capture-syntactic-environment' returns a form that will, when - transformed, call PROCEDURE on the current syntactic environment. - PROCEDURE should compute and return a new form to be transformed, - in that same syntactic environment, in place of the form. - - An example will make this clear. Suppose we wanted to define a - simple `loop-until' keyword equivalent to - (define-syntax loop-until - (syntax-rules () - ((loop-until id init test return step) - (letrec ((loop - (lambda (id) - (if test return (loop step))))) - (loop init))))) - - The following attempt at defining `loop-until' has a subtle bug: - (define-syntax loop-until - (transformer - (lambda (exp env) - (let ((id (cadr exp)) - (init (caddr exp)) - (test (cadddr exp)) - (return (cadddr (cdr exp))) - (step (cadddr (cddr exp))) - (close - (lambda (exp free) - (make-syntactic-closure env free exp)))) - `(letrec ((loop - (lambda (,id) - (if ,(close test (list id)) - ,(close return (list id)) - (loop ,(close step (list id))))))) - (loop ,(close init '()))))))) - - This definition appears to take all of the proper precautions to - prevent unintended captures. It carefully closes the - subexpressions in their original syntactic environment and it - leaves the `id' identifier free in the `test', `return', and - `step' expressions, so that it will be captured by the binding - introduced by the `lambda' expression. Unfortunately it uses the - identifiers `if' and `loop' within that `lambda' expression, so if - the user of `loop-until' just happens to use, say, `if' for the - identifier, it will be inadvertently captured. - - The syntactic environment that `if' and `loop' want to be exposed - to is the one just outside the `lambda' expression: before the - user's identifier is added to the syntactic environment, but after - the identifier loop has been added. - `capture-syntactic-environment' captures exactly that environment - as follows: - (define-syntax loop-until - (transformer - (lambda (exp env) - (let ((id (cadr exp)) - (init (caddr exp)) - (test (cadddr exp)) - (return (cadddr (cdr exp))) - (step (cadddr (cddr exp))) - (close - (lambda (exp free) - (make-syntactic-closure env free exp)))) - `(letrec ((loop - ,(capture-syntactic-environment - (lambda (env) - `(lambda (,id) - (,(make-syntactic-closure env '() `if) - ,(close test (list id)) - ,(close return (list id)) - (,(make-syntactic-closure env '() - `loop) - ,(close step (list id))))))))) - (loop ,(close init '()))))))) - - In this case, having captured the desired syntactic environment, - it is convenient to construct syntactic closures of the - identifiers `if' and the `loop' and use them in the body of the - `lambda'. - - A common use of `capture-syntactic-environment' is to get the - transformer environment of a macro transformer: - (transformer - (lambda (exp env) - (capture-syntactic-environment - (lambda (transformer-env) - ...)))) - -Identifiers -........... - - This section describes the procedures that create and manipulate -identifiers. Previous syntactic closure proposals did not have an -identifier data type - they just used symbols. The identifier data -type extends the syntactic closures facility to be compatible with the -high-level `syntax-rules' facility. - - As discussed earlier, an identifier is either a symbol or an "alias". -An alias is implemented as a syntactic closure whose "form" is an -identifier: - (make-syntactic-closure env '() 'a) - => an "alias" - - Aliases are implemented as syntactic closures because they behave just -like syntactic closures most of the time. The difference is that an -alias may be bound to a new value (for example by `lambda' or -`let-syntax'); other syntactic closures may not be used this way. If -an alias is bound, then within the scope of that binding it is looked -up in the syntactic environment just like any other identifier. - - Aliases are used in the implementation of the high-level facility -`syntax-rules'. A macro transformer created by `syntax-rules' uses a -template to generate its output form, substituting subforms of the -input form into the template. In a syntactic closures implementation, -all of the symbols in the template are replaced by aliases closed in -the transformer environment, while the output form itself is closed in -the usage environment. This guarantees that the macro transformation -is hygienic, without requiring the transformer to know the syntactic -roles of the substituted input subforms. - - - Function: identifier? OBJECT - Returns `#t' if OBJECT is an identifier, otherwise returns `#f'. - Examples: - (identifier? 'a) - => #t - (identifier? (make-syntactic-closure env '() 'a)) - => #t - (identifier? "a") - => #f - (identifier? #\a) - => #f - (identifier? 97) - => #f - (identifier? #f) - => #f - (identifier? '(a)) - => #f - (identifier? '#(a)) - => #f - - The predicate `eq?' is used to determine if two identifers are - "the same". Thus `eq?' can be used to compare identifiers exactly - as it would be used to compare symbols. Often, though, it is - useful to know whether two identifiers "mean the same thing". For - example, the `cond' macro uses the symbol `else' to identify the - final clause in the conditional. A macro transformer for `cond' - cannot just look for the symbol `else', because the `cond' form - might be the output of another macro transformer that replaced the - symbol `else' with an alias. Instead the transformer must look - for an identifier that "means the same thing" in the usage - environment as the symbol `else' means in the transformer - environment. - - - Function: identifier=? ENVIRONMENT1 IDENTIFIER1 ENVIRONMENT2 - IDENTIFIER2 - ENVIRONMENT1 and ENVIRONMENT2 must be syntactic environments, and - IDENTIFIER1 and IDENTIFIER2 must be identifiers. `identifier=?' - returns `#t' if the meaning of IDENTIFIER1 in ENVIRONMENT1 is the - same as that of IDENTIFIER2 in ENVIRONMENT2, otherwise it returns - `#f'. Examples: - - (let-syntax - ((foo - (transformer - (lambda (form env) - (capture-syntactic-environment - (lambda (transformer-env) - (identifier=? transformer-env 'x env 'x))))))) - (list (foo) - (let ((x 3)) - (foo)))) - => (#t #f) - - (let-syntax ((bar foo)) - (let-syntax - ((foo - (transformer - (lambda (form env) - (capture-syntactic-environment - (lambda (transformer-env) - (identifier=? transformer-env 'foo - env (cadr form)))))))) - (list (foo foo) - (foobar)))) - => (#f #t) - -Acknowledgements -................ - - The syntactic closures facility was invented by Alan Bawden and -Jonathan Rees. The use of aliases to implement `syntax-rules' was -invented by Alan Bawden (who prefers to call them "synthetic names"). -Much of this proposal is derived from an earlier proposal by Alan -Bawden. - - -File: slib.info, Node: Syntax-Case Macros, Next: Fluid-Let, Prev: Syntactic Closures, Up: Macros - -Syntax-Case Macros -================== - - `(require 'syntax-case)' - - - Function: macro:expand EXPRESSION - - Function: syncase:expand EXPRESSION - Returns scheme code with the macros and derived expression types of - EXPRESSION expanded to primitive expression types. - - - Function: macro:eval EXPRESSION - - Function: syncase:eval EXPRESSION - `macro:eval' returns the value of EXPRESSION in the current top - level environment. EXPRESSION can contain macro definitions. - Side effects of EXPRESSION will affect the top level environment. - - - Procedure: macro:load FILENAME - - Procedure: syncase:load FILENAME - FILENAME should be a string. If filename names an existing file, - the `macro:load' procedure reads Scheme source code expressions and - definitions from the file and evaluates them sequentially. These - source code expressions and definitions may contain macro - definitions. The `macro:load' procedure does not affect the - values returned by `current-input-port' and `current-output-port'. - - This is version 2.1 of `syntax-case', the low-level macro facility -proposed and implemented by Robert Hieb and R. Kent Dybvig. - - This version is further adapted by Harald Hanche-Olsen -<hanche@imf.unit.no> to make it compatible with, and easily usable -with, SLIB. Mainly, these adaptations consisted of: - - * Removing white space from `expand.pp' to save space in the - distribution. This file is not meant for human readers anyway... - - * Removed a couple of Chez scheme dependencies. - - * Renamed global variables used to minimize the possibility of name - conflicts. - - * Adding an SLIB-specific initialization file. - - * Removing a couple extra files, most notably the documentation (but - see below). - - If you wish, you can see exactly what changes were done by reading the -shell script in the file `syncase.sh'. - - The two PostScript files were omitted in order to not burden the SLIB -distribution with them. If you do intend to use `syntax-case', -however, you should get these files and print them out on a PostScript -printer. They are available with the original `syntax-case' -distribution by anonymous FTP in -`cs.indiana.edu:/pub/scheme/syntax-case'. - - In order to use syntax-case from an interactive top level, execute: - (require 'syntax-case) - (require 'repl) - (repl:top-level macro:eval) - See the section Repl (*Note Repl::) for more information. - - To check operation of syntax-case get -`cs.indiana.edu:/pub/scheme/syntax-case', and type - (require 'syntax-case) - (syncase:sanity-check) - - Beware that `syntax-case' takes a long time to load - about 20s on a -SPARCstation SLC (with SCM) and about 90s on a Macintosh SE/30 (with -Gambit). - -Notes ------ - - All R4RS syntactic forms are defined, including `delay'. Along with -`delay' are simple definitions for `make-promise' (into which `delay' -expressions expand) and `force'. - - `syntax-rules' and `with-syntax' (described in `TR356') are defined. - - `syntax-case' is actually defined as a macro that expands into calls -to the procedure `syntax-dispatch' and the core form `syntax-lambda'; -do not redefine these names. - - Several other top-level bindings not documented in TR356 are created: - the "hooks" in `hooks.ss' - - the `build-' procedures in `output.ss' - - `expand-syntax' (the expander) - - The syntax of define has been extended to allow `(define ID)', which -assigns ID to some unspecified value. - - We have attempted to maintain R4RS compatibility where possible. The -incompatibilities should be confined to `hooks.ss'. Please let us know -if there is some incompatibility that is not flagged as such. - - Send bug reports, comments, suggestions, and questions to Kent Dybvig -(dyb@iuvax.cs.indiana.edu). - -Note from maintainer --------------------- - - Included with the `syntax-case' files was `structure.scm' which -defines a macro `define-structure'. There is no documentation for this -macro and it is not used by any code in SLIB. - - -File: slib.info, Node: Fluid-Let, Next: Yasos, Prev: Syntax-Case Macros, Up: Macros - -Fluid-Let -========= - - `(require 'fluid-let)' - - - Syntax: fluid-let `(BINDINGS ...)' FORMS... - - (fluid-let ((VARIABLE INIT) ...) - EXPRESSION EXPRESSION ...) - - The INITs are evaluated in the current environment (in some -unspecified order), the current values of the VARIABLEs are saved, the -results are assigned to the VARIABLEs, the EXPRESSIONs are evaluated -sequentially in the current environment, the VARIABLEs are restored to -their original values, and the value of the last EXPRESSION is returned. - - The syntax of this special form is similar to that of `let', but -`fluid-let' temporarily rebinds existing VARIABLEs. Unlike `let', -`fluid-let' creates no new bindings; instead it *assigns* the values of -each INIT to the binding (determined by the rules of lexical scoping) -of its corresponding VARIABLE. - - -File: slib.info, Node: Yasos, Prev: Fluid-Let, Up: Macros - -Yasos -===== - - `(require 'oop)' or `(require 'yasos)' - - `Yet Another Scheme Object System' is a simple object system for -Scheme based on the paper by Norman Adams and Jonathan Rees: `Object -Oriented Programming in Scheme', Proceedings of the 1988 ACM Conference -on LISP and Functional Programming, July 1988 [ACM #552880]. - - Another reference is: - - Ken Dickey. Scheming with Objects `AI Expert' Volume 7, Number 10 -(October 1992), pp. 24-33. - -* Menu: - -* Yasos terms:: Definitions and disclaimer. -* Yasos interface:: The Yasos macros and procedures. -* Setters:: Dylan-like setters in Yasos. -* Yasos examples:: Usage of Yasos and setters. - - -File: slib.info, Node: Yasos terms, Next: Yasos interface, Prev: Yasos, Up: Yasos - -Terms ------ - -"Object" - Any Scheme data object. - -"Instance" - An instance of the OO system; an "object". - -"Operation" - A METHOD. - -*Notes:* - The object system supports multiple inheritance. An instance can - inherit from 0 or more ancestors. In the case of multiple - inherited operations with the same identity, the operation used is - that from the first ancestor which contains it (in the ancestor - `let'). An operation may be applied to any Scheme data - object--not just instances. As code which creates instances is - just code, there are no "classes" and no meta-ANYTHING. Method - dispatch is by a procedure call a la CLOS rather than by `send' - syntax a la Smalltalk. - -*Disclaimer:* - There are a number of optimizations which can be made. This - implementation is expository (although performance should be quite - reasonable). See the L&FP paper for some suggestions. - - -File: slib.info, Node: Yasos interface, Next: Setters, Prev: Yasos terms, Up: Yasos - -Interface ---------- - - - Syntax: define-operation `('OPNAME SELF ARG ...`)' DEFAULT-BODY - Defines a default behavior for data objects which don't handle the - operation OPNAME. The default default behavior (for an empty - DEFAULT-BODY) is to generate an error. - - - Syntax: define-predicate OPNAME? - Defines a predicate OPNAME?, usually used for determining the - "type" of an object, such that `(OPNAME? OBJECT)' returns `#t' if - OBJECT has an operation OPNAME? and `#f' otherwise. - - - Syntax: object `((NAME SELF ARG ...) BODY)' ... - Returns an object (an instance of the object system) with - operations. Invoking `(NAME OBJECT ARG ...' executes the BODY of - the OBJECT with SELF bound to OBJECT and with argument(s) ARG.... - - - Syntax: object-with-ancestors `(('ANCESTOR1 INIT1`)' ...`)' - OPERATION ... - A `let'-like form of `object' for multiple inheritance. It - returns an object inheriting the behaviour of ANCESTOR1 etc. An - operation will be invoked in an ancestor if the object itself does - not provide such a method. In the case of multiple inherited - operations with the same identity, the operation used is the one - found in the first ancestor in the ancestor list. - - - Syntax: operate-as COMPONENT OPERATION SELF ARG ... - Used in an operation definition (of SELF) to invoke the OPERATION - in an ancestor COMPONENT but maintain the object's identity. Also - known as "send-to-super". - - - Procedure: print OBJ PORT - A default `print' operation is provided which is just `(format - PORT OBJ)' (*Note Format::) for non-instances and prints OBJ - preceded by `#<INSTANCE>' for instances. - - - Function: size OBJ - The default method returns the number of elements in OBJ if it is - a vector, string or list, `2' for a pair, `1' for a character and - by default id an error otherwise. Objects such as collections - (*Note Collections::) may override the default in an obvious way. - - -File: slib.info, Node: Setters, Next: Yasos examples, Prev: Yasos interface, Up: Yasos - -Setters -------- - - "Setters" implement "generalized locations" for objects associated -with some sort of mutable state. A "getter" operation retrieves a -value from a generalized location and the corresponding setter -operation stores a value into the location. Only the getter is named - -the setter is specified by a procedure call as below. (Dylan uses -special syntax.) Typically, but not necessarily, getters are access -operations to extract values from Yasos objects (*Note Yasos::). -Several setters are predefined, corresponding to getters `car', `cdr', -`string-ref' and `vector-ref' e.g., `(setter car)' is equivalent to -`set-car!'. - - This implementation of setters is similar to that in Dylan(TM) -(`Dylan: An object-oriented dynamic language', Apple Computer Eastern -Research and Technology). Common LISP provides similar facilities -through `setf'. - - - Function: setter GETTER - Returns the setter for the procedure GETTER. E.g., since - `string-ref' is the getter corresponding to a setter which is - actually `string-set!': - (define foo "foo") - ((setter string-ref) foo 0 #\F) ; set element 0 of foo - foo => "Foo" - - - Syntax: set PLACE NEW-VALUE - If PLACE is a variable name, `set' is equivalent to `set!'. - Otherwise, PLACE must have the form of a procedure call, where the - procedure name refers to a getter and the call indicates an - accessible generalized location, i.e., the call would return a - value. The return value of `set' is usually unspecified unless - used with a setter whose definition guarantees to return a useful - value. - (set (string-ref foo 2) #\O) ; generalized location with getter - foo => "FoO" - (set foo "foo") ; like set! - foo => "foo" - - - Procedure: add-setter GETTER SETTER - Add procedures GETTER and SETTER to the (inaccessible) list of - valid setter/getter pairs. SETTER implements the store operation - corresponding to the GETTER access operation for the relevant - state. The return value is unspecified. - - - Procedure: remove-setter-for GETTER - Removes the setter corresponding to the specified GETTER from the - list of valid setters. The return value is unspecified. - - - Syntax: define-access-operation GETTER-NAME - Shorthand for a Yasos `define-operation' defining an operation - GETTER-NAME that objects may support to return the value of some - mutable state. The default operation is to signal an error. The - return value is unspecified. - - -File: slib.info, Node: Yasos examples, Prev: Setters, Up: Yasos - -Examples --------- - - (define-operation (print obj port) - (format port - (if (instance? obj) "#<instance>" "~s") - obj)) - - (define-operation (SIZE obj) - (cond - ((vector? obj) (vector-length obj)) - ((list? obj) (length obj)) - ((pair? obj) 2) - ((string? obj) (string-length obj)) - ((char? obj) 1) - (else - (error "Operation not supported: size" obj)))) - - (define-predicate cell?) - (define-operation (fetch obj)) - (define-operation (store! obj newValue)) - - (define (make-cell value) - (object - ((cell? self) #t) - ((fetch self) value) - ((store! self newValue) - (set! value newValue) - newValue) - ((size self) 1) - ((print self port) - (format port "#<Cell: ~s>" (fetch self))))) - - (define-operation (discard obj value) - (format #t "Discarding ~s~%" value)) - - (define (make-filtered-cell value filter) - (object-with-ancestors ((cell (make-cell value))) - ((store! self newValue) - (if (filter newValue) - (store! cell newValue) - (discard self newValue))))) - - (define-predicate array?) - (define-operation (array-ref array index)) - (define-operation (array-set! array index value)) - - (define (make-array num-slots) - (let ((anArray (make-vector num-slots))) - (object - ((array? self) #t) - ((size self) num-slots) - ((array-ref self index) (vector-ref anArray index)) - ((array-set! self index newValue) (vector-set! anArray index newValue)) - ((print self port) (format port "#<Array ~s>" (size self)))))) - - (define-operation (position obj)) - (define-operation (discarded-value obj)) - - (define (make-cell-with-history value filter size) - (let ((pos 0) (most-recent-discard #f)) - (object-with-ancestors - ((cell (make-filtered-call value filter)) - (sequence (make-array size))) - ((array? self) #f) - ((position self) pos) - ((store! self newValue) - (operate-as cell store! self newValue) - (array-set! self pos newValue) - (set! pos (+ pos 1))) - ((discard self value) - (set! most-recent-discard value)) - ((discarded-value self) most-recent-discard) - ((print self port) - (format port "#<Cell-with-history ~s>" (fetch self)))))) - - (define-access-operation fetch) - (add-setter fetch store!) - (define foo (make-cell 1)) - (print foo #f) - => "#<Cell: 1>" - (set (fetch foo) 2) - => - (print foo #f) - => "#<Cell: 2>" - (fetch foo) - => 2 - - -File: slib.info, Node: Numerics, Next: Procedures, Prev: Macros, Up: Top - -Numerics -******** - -* Menu: - -* Bit-Twiddling:: 'logical -* Modular Arithmetic:: 'modular -* Prime Testing and Generation:: 'primes -* Prime Factorization:: 'factor -* Random Numbers:: 'random -* Cyclic Checksum:: 'make-crc -* Plotting:: 'charplot -* Root Finding:: - - -File: slib.info, Node: Bit-Twiddling, Next: Modular Arithmetic, Prev: Numerics, Up: Numerics - -Bit-Twiddling -============= - - `(require 'logical)' - - The bit-twiddling functions are made available through the use of the -`logical' package. `logical' is loaded by inserting `(require -'logical)' before the code that uses these functions. - - - Function: logand N1 N1 - Returns the integer which is the bit-wise AND of the two integer - arguments. - - Example: - (number->string (logand #b1100 #b1010) 2) - => "1000" - - - Function: logior N1 N2 - Returns the integer which is the bit-wise OR of the two integer - arguments. - - Example: - (number->string (logior #b1100 #b1010) 2) - => "1110" - - - Function: logxor N1 N2 - Returns the integer which is the bit-wise XOR of the two integer - arguments. - - Example: - (number->string (logxor #b1100 #b1010) 2) - => "110" - - - Function: lognot N - Returns the integer which is the 2s-complement of the integer - argument. - - Example: - (number->string (lognot #b10000000) 2) - => "-10000001" - (number->string (lognot #b0) 2) - => "-1" - - - Function: logtest J K - (logtest j k) == (not (zero? (logand j k))) - - (logtest #b0100 #b1011) => #f - (logtest #b0100 #b0111) => #t - - - Function: logbit? INDEX J - (logbit? index j) == (logtest (integer-expt 2 index) j) - - (logbit? 0 #b1101) => #t - (logbit? 1 #b1101) => #f - (logbit? 2 #b1101) => #t - (logbit? 3 #b1101) => #t - (logbit? 4 #b1101) => #f - - - Function: ash INT COUNT - Returns an integer equivalent to `(inexact->exact (floor (* INT - (expt 2 COUNT))))'. - - Example: - (number->string (ash #b1 3) 2) - => "1000" - (number->string (ash #b1010 -1) 2) - => "101" - - - Function: logcount N - Returns the number of bits in integer N. If integer is positive, - the 1-bits in its binary representation are counted. If negative, - the 0-bits in its two's-complement binary representation are - counted. If 0, 0 is returned. - - Example: - (logcount #b10101010) - => 4 - (logcount 0) - => 0 - (logcount -2) - => 1 - - - Function: integer-length N - Returns the number of bits neccessary to represent N. - - Example: - (integer-length #b10101010) - => 8 - (integer-length 0) - => 0 - (integer-length #b1111) - => 4 - - - Function: integer-expt N K - Returns N raised to the non-negative integer exponent K. - - Example: - (integer-expt 2 5) - => 32 - (integer-expt -3 3) - => -27 - - - Function: bit-extract N START END - Returns the integer composed of the START (inclusive) through END - (exclusive) bits of N. The STARTth bit becomes the 0-th bit in - the result. - - Example: - (number->string (bit-extract #b1101101010 0 4) 2) - => "1010" - (number->string (bit-extract #b1101101010 4 9) 2) - => "10110" - - -File: slib.info, Node: Modular Arithmetic, Next: Prime Testing and Generation, Prev: Bit-Twiddling, Up: Numerics - -Modular Arithmetic -================== - - `(require 'modular)' - - - Function: extended-euclid N1 N2 - Returns a list of 3 integers `(d x y)' such that d = gcd(N1, N2) = - N1 * x + N2 * y. - - - Function: symmetric:modulus N - Returns `(quotient (+ -1 n) -2)' for positive odd integer N. - - - Function: modulus->integer MODULUS - Returns the non-negative integer characteristic of the ring formed - when MODULUS is used with `modular:' procedures. - - - Function: modular:normalize MODULUS N - Returns the integer `(modulo N (modulus->integer MODULUS))' in the - representation specified by MODULUS. - -The rest of these functions assume normalized arguments; That is, the -arguments are constrained by the following table: - -For all of these functions, if the first argument (MODULUS) is: -`positive?' - Work as before. The result is between 0 and MODULUS. - -`zero?' - The arguments are treated as integers. An integer is returned. - -`negative?' - The arguments and result are treated as members of the integers - modulo `(+ 1 (* -2 MODULUS))', but with "symmetric" - representation; i.e. `(<= (- MODULUS) N MODULUS)'. - -If all the arguments are fixnums the computation will use only fixnums. - - - Function: modular:invertable? MODULUS K - Returns `#t' if there exists an integer n such that K * n == 1 mod - MODULUS, and `#f' otherwise. - - - Function: modular:invert MODULUS K2 - Returns an integer n such that 1 = (n * K2) mod MODULUS. If K2 - has no inverse mod MODULUS an error is signaled. - - - Function: modular:negate MODULUS K2 - Returns (-K2) mod MODULUS. - - - Function: modular:+ MODULUS K2 K3 - Returns (K2 + K3) mod MODULUS. - - - Function: modular:- MODULUS K2 K3 - Returns (K2 - K3) mod MODULUS. - - - Function: modular:* MODULUS K2 K3 - Returns (K2 * K3) mod MODULUS. - - The Scheme code for `modular:*' with negative MODULUS is not - completed for fixnum-only implementations. - - - Function: modular:expt MODULUS K2 K3 - Returns (K2 ^ K3) mod MODULUS. - - -File: slib.info, Node: Prime Testing and Generation, Next: Prime Factorization, Prev: Modular Arithmetic, Up: Numerics - -Prime Testing and Generation -============================ - - `(require 'primes)' - - This package tests and generates prime numbers. The strategy used is -as follows: - - First, use trial division by small primes (primes less than 1000) - to quickly weed out composites with small factors. As a side - benefit, this makes the test precise for numbers up to one million. - - Second, apply the Miller-Rabin primality test to detect (with high - probability) any remaining composites. - - The Miller-Rabin test is a Monte-Carlo test--in other words, it's fast -and it gets the right answer with high probability. For a candidate -that *is* prime, the Miller-Rabin test is certain to report "prime"; it -will never report "composite". However, for a candidate that is -composite, there is a (small) probability that the Miller-Rabin test -will erroneously report "prime". This probability can be made -arbitarily small by adjusting the number of iterations of the -Miller-Rabin test. - - - Function: probably-prime? CANDIDATE - - Function: probably-prime? CANDIDATE ITER - Returns `#t' if `candidate' is probably prime. The optional - parameter `iter' controls the number of iterations of the - Miller-Rabin test. The probability of a composite candidate being - mistaken for a prime is at most `(1/4)^iter'. The default value of - `iter' is 15, which makes the probability less than 1 in 10^9. - - - - Function: primes< START COUNT - - Function: primes< START COUNT ITER - - Function: primes> START COUNT - - Function: primes> START COUNT ITER - Returns a list of the first `count' odd probable primes less (more) - than or equal to `start'. The optional parameter `iter' controls - the number of iterations of the Miller-Rabin test for each - candidate. The probability of a composite candidate being - mistaken for a prime is at most `(1/4)^iter'. The default value - of `iter' is 15, which makes the probability less than 1 in 10^9. - - -* Menu: - -* The Miller-Rabin Test:: How the Miller-Rabin test works - - -File: slib.info, Node: The Miller-Rabin Test, Prev: Prime Testing and Generation, Up: Prime Testing and Generation - -Theory ------- - - Rabin and Miller's result can be summarized as follows. Let `p' (the -candidate prime) be any odd integer greater than 2. Let `b' (the -"base") be an integer in the range `2 ... p-1'. There is a fairly -simple Boolean function--call it `C', for "Composite"--with the -following properties: - If `p' is prime, `C(p, b)' is false for all `b' in the range `2 - ... p-1'. - - If `p' is composite, `C(p, b)' is false for at most 1/4 of all `b' - in the range ` 2 ... p-1'. (If the test fails for base `b', `p' - is called a *strong pseudo-prime to base `b'*.) - - For details of `C', and why it fails for at most 1/4 of the potential -bases, please consult a book on number theory or cryptography such as -"A Course in Number Theory and Cryptography" by Neal Koblitz, published -by Springer-Verlag 1994. - - There is nothing probablistic about this result. It's true for all -`p'. If we had time to test `(1/4)p + 1' different bases, we could -definitively determine the primality of `p'. For large candidates, -that would take much too long--much longer than the simple approach of -dividing by all numbers up to `sqrt(p)'. This is where probability -enters the picture. - - Suppose we have some candidate prime `p'. Pick a random integer `b' -in the range `2 ... p-1'. Compute `C(p,b)'. If `p' is prime, the -result will certainly be false. If `p' is composite, the probability -is at most 1/4 that the result will be false (demonstrating that `p' is -a strong pseudoprime to base `b'). The test can be repeated with other -random bases. If `p' is prime, each test is certain to return false. -If `p' is composite, the probability of `C(p,b)' returning false is at -most 1/4 for each test. Since the `b' are chosen at random, the tests -outcomes are independent. So if `p' is composite and the test is -repeated, say, 15 times, the probability of it returning false all -fifteen times is at most (1/4)^15, or about 10^-9. If the test is -repeated 30 times, the probability of failure drops to at most 8.3e-25. - - Rabin and Miller's result holds for *all* candidates `p'. However, -if the candidate `p' is picked at random, the probability of the -Miller-Rabin test failing is much less than the computed bound. This -is because, for *most* composite numbers, the fraction of bases that -cause the test to fail is much less than 1/4. For example, if you pick -a random odd number less than 1000 and apply the Miller-Rabin test with -only 3 random bases, the computed failure bound is (1/4)^3, or about -1.6e-2. However, the actual probability of failure is much less--about -7.2e-5. If you accidentally pick 703 to test for primality, the -probability of failure is (161/703)^3, or about 1.2e-2, which is almost -as high as the computed bound. This is because 703 is a strong -pseudoprime to 161 bases. But if you pick at random there is only a -small chance of picking 703, and no other number less than 1000 has -that high a percentage of pseudoprime bases. - - The Miller-Rabin test is sometimes used in a slightly different -fashion, where it can, at least in principle, cause problems. The -weaker version uses small prime bases instead of random bases. If you -are picking candidates at random and testing for primality, this works -well since very few composites are strong pseudo-primes to small prime -bases. (For example, there is only one composite less than 2.5e10 that -is a strong pseudo-prime to the bases 2, 3, 5, and 7.) The problem -with this approach is that once a candidate has been picked, the test is -deterministic. This distinction is subtle, but real. With the -randomized test, for *any* candidate you pick--even if your -candidate-picking procedure is strongly biased towards troublesome -numbers, the test will work with high probability. With the -deterministic version, for any particular candidate, the test will -either work (with probability 1), or fail (with probability 1). It -won't fail for very many candidates, but that won't be much consolation -if your candidate-picking procedure is somehow biased toward troublesome -numbers. - - -File: slib.info, Node: Prime Factorization, Next: Random Numbers, Prev: Prime Testing and Generation, Up: Numerics - -Prime Factorization -=================== - - `(require 'factor)' - - - Function: factor K - Returns a list of the prime factors of K. The order of the - factors is unspecified. In order to obtain a sorted list do - `(sort! (factor k) <)'. - - *Note:* The rest of these procedures implement the Solovay-Strassen -primality test. This test has been superseeded by the faster *Note -probably-prime?: Prime Testing and Generation. However these are left -here as they take up little space and may be of use to an -implementation without bignums. - - See Robert Solovay and Volker Strassen, `A Fast Monte-Carlo Test for -Primality', SIAM Journal on Computing, 1977, pp 84-85. - - - Function: jacobi-symbol P Q - Returns the value (+1, -1, or 0) of the Jacobi-Symbol of exact - non-negative integer P and exact positive odd integer Q. - - - Function: prime? P - Returns `#f' if P is composite; `#t' if P is prime. There is a - slight chance `(expt 2 (- prime:trials))' that a composite will - return `#t'. - - - Function: prime:trials - Is the maxinum number of iterations of Solovay-Strassen that will - be done to test a number for primality. - - -File: slib.info, Node: Random Numbers, Next: Cyclic Checksum, Prev: Prime Factorization, Up: Numerics - -Random Numbers -============== - - `(require 'random)' - - - Procedure: random N - - Procedure: random N STATE - Accepts a positive integer or real N and returns a number of the - same type between zero (inclusive) and N (exclusive). The values - returned have a uniform distribution. - - The optional argument STATE must be of the type produced by - `(make-random-state)'. It defaults to the value of the variable - `*random-state*'. This object is used to maintain the state of the - pseudo-random-number generator and is altered as a side effect of - the `random' operation. - - - Variable: *random-state* - Holds a data structure that encodes the internal state of the - random-number generator that `random' uses by default. The nature - of this data structure is implementation-dependent. It may be - printed out and successfully read back in, but may or may not - function correctly as a random-number state object in another - implementation. - - - Procedure: make-random-state - - Procedure: make-random-state STATE - Returns a new object of type suitable for use as the value of the - variable `*random-state*' and as a second argument to `random'. - If argument STATE is given, a copy of it is returned. Otherwise a - copy of `*random-state*' is returned. - - If inexact numbers are support by the Scheme implementation, -`randinex.scm' will be loaded as well. `randinex.scm' contains -procedures for generating inexact distributions. - - - Procedure: random:uniform STATE - Returns an uniformly distributed inexact real random number in the - range between 0 and 1. - - - Procedure: random:solid-sphere! VECT - - Procedure: random:solid-sphere! VECT STATE - Fills VECT with inexact real random numbers the sum of whose - squares is less than 1.0. Thinking of VECT as coordinates in - space of dimension N = `(vector-length VECT)', the coordinates are - uniformly distributed within the unit N-shere. The sum of the - squares of the numbers is returned. - - - Procedure: random:hollow-sphere! VECT - - Procedure: random:hollow-sphere! VECT STATE - Fills VECT with inexact real random numbers the sum of whose - squares is equal to 1.0. Thinking of VECT as coordinates in space - of dimension n = `(vector-length VECT)', the coordinates are - uniformly distributed over the surface of the unit n-shere. - - - Procedure: random:normal - - Procedure: random:normal STATE - Returns an inexact real in a normal distribution with mean 0 and - standard deviation 1. For a normal distribution with mean M and - standard deviation D use `(+ M (* D (random:normal)))'. - - - Procedure: random:normal-vector! VECT - - Procedure: random:normal-vector! VECT STATE - Fills VECT with inexact real random numbers which are independent - and standard normally distributed (i.e., with mean 0 and variance - 1). - - - Procedure: random:exp - - Procedure: random:exp STATE - Returns an inexact real in an exponential distribution with mean - 1. For an exponential distribution with mean U use (* U - (random:exp)). - |