# Documentation for '`swindle/extra.ss`'

This module defines some additional useful functionality which requires Swindle.

`(defstruct `<struct-name>` ([super]) slot ...)` | [syntax]

      This is just a Swindle-style syntax for one of
        (define-struct struct-name (slot ...) (make-inspector))
        (define-struct (struct-name super) (slot ...) (make-inspector))
      with an additional binding of <struct-name> to the Swindle class that
      is computed by 'struct-type->class'.  The '(make-inspector)' is needed
      to make this a struct that we can access information on.  Note that in
      method specifiers, the 'struct:foo' which is defined by
      'define-struct' can be used just like '<foo>'.  What all this means is
      that you can use MzScheme structs if you just want Swindle's generic
      functions, but use built in structs that are more efficient since they
      are part of the implementation.  For example:

        => (defstruct <foo> () x y)
        => <foo>
        #<primitive-class:foo>
        => (defmethod (bar [x <foo>]) (foo-x x))
        => (bar (make-foo 1 2))
        1
        => (defmethod (bar [x struct:foo]) (foo-x x))
        => (bar (make-foo 3 4))
        3
        => (generic-methods bar)
        (#<method:bar:foo>)
        => (defstruct <foo2> (foo) z)
        => (bar (make-foo2 10 11 12))
        10

      To make things even easier, the super-struct can be written using a
      "<...>" syntax which will be stripped, and appropriate methods are
      added to 'allocate-instance' and 'initialize' so structs can be built
      using keywords:

        => (defstruct <foo3> (<foo>) z)
        => (foo-x (make <foo3> :z 3 :y 2 :x 1))
        1
        => (foo3-z (make <foo3> :z 3 :y 2 :x 2))
        3

      The '<struct-name>' identifier *must* be of this form -- enclosed in
      "<>"s.  This restriction is due to the fact that defining an MzScheme
      struct 'foo', makes 'foo' bound as a syntax object to something that
      cannot be used in any other way.

`(with-slots obj (slot ...) body ...)` | [syntax]

      Evaluate the body in an environment where each 'slot' is defined as a
      symbol-macro that accesses the corresponding slot value of 'obj'.
      Each 'slot' is either an identifier 'id' which makes it stand for
      `(slot-ref obj 'id)', or `(id slot)' which makes 'id' stand for
      `(slot-ref obj slot)'.

`(with-accessors obj (accessor ...) body ...)` | [syntax]

      Evaluate the body in an environment where each 'accessor' is defined
      as a symbol-macro that accesses 'obj'.  Each 'accessor' is either an
      identifier 'id' which makes it stand for `(id obj)', or
      `(id accessor)' which makes 'id' stand for `(accessor obj);.

`(as class obj)` | [generic]

      Converts 'obj' to an instance of 'class'.  This is a convenient
      generic wrapper around Scheme conversion functions (functions that
      look like 'foo->bar'), but can be used for other classes too.

`(add-as-method from-class to-class op ...)` | [procedure]

      Adds a method to 'as' that will use the function 'op' to convert
      instances of 'from-class' to instances of 'to-class'.  More operators
      can be used which will make this use their composition.  This is used
      to initialize 'as' with the standard Scheme conversion functions.

`(equals? x y)` | [generic]

      A generic that compares 'x' and 'y'.  It has an around method that
      will stop and return '#t' if the two arguments are 'equal?'.  It is
      intended for user-defined comparison between any instances.

`(add-equals?-method class pred?)` | [procedure]

      Adds a method to 'equals?' that will use the given 'pred?' predicate
      to compare instances of 'class'.

`(class+slots-equals? x y)` | [procedure]

      This is a predicate function (not a generic function) that will
      succeed if 'x' and 'y' are instances of the same class, and all of
      their corresponding slots are 'equals?'.  This is useful as a quick
      default for comparing simple classes (but be careful and avoid
      circularity problems).

`(make-equals?-compare-class+slots class)` | [procedure]

      Make 'class' use 'class+slots-equals?' for comparison with 'equals?'.

`(add x ...)` | [generic]

      A generic addition operation, initialized for some Scheme types
      (numbers (+), lists (append), strings (string-append), symbols
      (symbol-append), procedures (compose), and vectors).  It dispatches
      only on the first argument.

`(add-add-method class op)` | [procedure]

      Add a method to 'add' that will use 'op' to add objects of class
      'class'.

`(len x)` | [generic]

      A generic length operation, initialized for some Scheme types (lists
      (length), strings (string-length), vectors (vector-length)).

`(add-len-method class op)` | [procedure]

      Add a method to 'len' that will use 'op' to measure objects length for
      instances of 'class'.

`(ref x indexes...)` | [generic]

      A generic reference operation, initialized for some Scheme types and
      instances.  Methods are predefined for lists, vectors, strings,
      objects, hash-tables, boxes, promises, parameters, and namespaces.

`(add-ref-method class op)` | [procedure]

      Add a method to 'ref' that will use 'op' to reference objects of class
      'class'.

`(put! x v indexes)` | [generic]

      A generic setter operation, initialized for some Scheme types and
      instances.  The new value comes first so it is possible to add methods
      to specialize on it.  Methods are predefined for lists, vectors,
      strings, objects, hash-tables, boxes, parameters, and namespaces.

`(add-put!-method class op)` | [procedure]

      Add a method to 'put!' that will use 'op' to change objects of class
      'class'.

`(set-ref! x indexes... v)` | [syntax]

      This syntax will just translate to `(put! x v indexes...)'.  It makes
      it possible to make `(set! (ref ...) ...)' work with 'put!'.

## Generic-based printing mechanism

`*print-level*` | [parameter]
`*print-length*` | [parameter]

      These parameters control how many levels deep a nested data object
      will print, and how many elements are printed at each level.  '#f'
      means no limit.  The effect is similar to the corresponding globals in
      Lisp.  Only affects printing of container objects (like lists, vectors
      and structures).

`(print-object obj esc? port)` | [generic]

      Prints 'obj' on 'port' using the above parameters -- the effect of
      'esc?' being true is to use a 'write'-like printout rather than a
      'display'-like printout when it is false.  Primitive Scheme values are
      printed normally, Swindle objects are printed using the un-'read'-able
      "#<...>" sequence unless a method that handles them is defined.  For
      this printout, objects with a 'name' slot are printed using that name
      (and their class's name).

      Warning: this is the method used for user-interaction output, errors
      etc.  Make sure you only define reliable methods for it.

`(name-sans-<> name)` | [procedure]

      Given a string or symbol for name, return a string where the outermost
      set of angle brackets have been stripped if they are present.  This is
      handy if you are writing your own print-object methods.

`(print-object-with-slots obj esc? port)` | [procedure]

      This is a printer function that can be used for classes where the
      desired output shows slot values.  Note that it is a simple function,
      which should be embedded in a method that is to be added to
      'print-object'.

`(display-object obj [port])` | [procedure]
`(write-object obj [port])` | [procedure]

      Used to display and write an object using 'print-object'.  Used as the
      corresponding output handler functions.

`(object->string obj [esc? = #t])` | [procedure]

      Convert the given 'obj' to a string using its printed form.

`(install-swindle-printer)` | [procedure]

      In MzScheme, output is configurable on a per-port basis.  Use this
      function to install Swindle's 'display-object' and 'write-object' on
      the current output and error ports whenever they are changed
      ('swindle' does that on startup).  This makes it possible to see
      Swindle values in errors, when using 'printf' etc.

## Simple matching

`match-failure` | [value]

      The result for a matcher function application that failed.  You can
      return this value from a matcher function in a <matcher> so the next
      matching one will get invoked.

`(matching? matcher value)` | [procedure]

      The 'matcher' argument is a value of any type, which is matched
      against the given 'value'.  For most values matching means being equal
      (using 'equals?')  to, but there are some exceptions: class objects
      are tested with 'instance-of?', functions are used as predicates,
      literals are used with equals?, pairs are compared recursively and
      regexps are used with regexp-match.

`(let/match pattern value body ...)` | [syntax]

      Match the 'value' against the given 'pattern', and evaluate the body
      on a success.  It is an error for the match to fail.  Variables that
      get bound in the matching process can be used in the body.

      The pattern specification has a complex syntax as follows:
      - simple values (not symbols) are compared with 'matching?' above;
      - :x                 keywords are also used as literal values;
      - *                  is a wildcard that always succeeds;
      - ???                matches the '???' value;
      - (lambda ...)       use the resulting closure value (for predicates);
      - (quote ...)        use the contents as a simple value;
      - (quasiquote ...)   same;
      - (V := P)           assign the variable V to the value matched by P;
      - V                  for a variable name V that was not part of the
                           pattern so far, this matches anything and binds V
                           to the value -- the same as (V := *);
      - (! E)              evaluate E, use the result as a literal value;
      - (!! E)             evaluate E, continue matching only if it is true;
      - (V when E)         same as (and V (!! E));
      - (and P ...)        combine the matchers with and, can bind any
                           variables in all parts;
      - (or P ...)         combine the matchers with or, bound variables are
                           only from the successful form;
      - (if A B C)         same as (or (and A B) C);
      - (F => P)           continue matching P with (F x) (where is x is the
                           current matched object);
      - (V :: P ...)       same as (and (! V) P...), useful for class forms
                           like (<class> :: (foo => f) ...);
      - (make <class> ...) if the value is an instance of <class>, then
                           continue by the '...' part which is a list of
                           slot names and patterns -- a slot name is either
                           :foo or 'foo, and the pattern will be matched
                           against the contents of that slot in the original
                           <class> instance;
      - ???                matches the unspecified value ('???' in tiny-clos)
      - (regexp R)         convert R to a regexp and use that to match
                           strings;
      - (regexp R P ...)   like the above, but continue matching the result
                           with `(P ...)' so it can bind variables to the
                           result (something like `(regexp "a(x?)b" x y)'
                           will bind 'x' to the 'regexp-match' result, and
                           'y' to a match of the sub-regexp part);
      - (...)              other lists - match the elements of a list
                           recursively (can use a dot suffix for a "rest"
                           arguments).

    Note that variable names match anything and bind the name to the result,
    except when the name was already seen -- where the previously bound
    value is used, allowing patterns where some parts should match the same
    value.  (A name was 'seen' if it was previously used in the pattern
    except on different branches of an 'or' pattern.)

`(matcher pattern body ...)` | [syntax]

      This creates a matcher function, using the given 'pattern' which will
      be matched with the list of given arguments on usage.  If the given
      arguments fail to match on an application, an error will be raised.

`(match x (pattern expr ...) ...)` | [syntax]

      This is similar to a 'cond' statement but each clause starts with a
      pattern, possibly binding variables for its body.  It also handles
      'else' as a last clause.

``<matcher>`` | [class]

      A class similar to a generic function, that holds matcher functions
      such as the ones created by the 'matcher' macro.  It has three slots:
      'name', 'default' (either a default value or a function that is
      applied to the arguments to produce the default value), and 'matchers'
      (a list of matcher functions).

      Instance of '<entity-class>', subclass of '<generic>'.

`(defmatcher (name pattern) body ...)` | [syntax]
`(defmatcher0 (name pattern) body ...)` | [syntax]

      These macros define a matcher (if not defined yet), create a matcher
      function and add it to the matcher (either at the end (defmatcher) or
      at the beginning (defmatcher0)).

## An amb macro

    This is added just because it is too much fun to miss.  To learn about
    'amb', look for it in the Help Desk, in the "Teach Yourself Scheme in
    Fixnum Days" on-line manual.

`(amb expr ...)` | [syntax]

      Execute forms in a nondeterministic way: each form is tried in
      sequence, and if one fails then evaluation continues with the next.
      '(amb)' fails immediately.

`(amb-assert cond)` | [procedure]

      Asserts that 'cond' is true, fails otherwise.

`(amb-collect expr)` | [syntax]

      Evaluate expr, using amb-fail repeatedly until all options are
      exhausted and returns the list of all results.

## Very basic UI - works also in console mode

    The following defines some hacked UI functions that works using MrEd GUI
    if it is available, or the standard error and input ports otherwise.
    The check is done by looking for a GUI global binding.

`*dialog-title*` | [parameter]

      This parameter defines the title used for the hacked UI interface.

`(message fmt-string arg ...)` | [procedure]

      Like 'printf' with a prefix title, or using a message dialog box.

`(ok/cancel? fmt-string arg ...)` | [procedure]
`(yes/no? fmt-string arg ...)` | [procedure]

      These functions are similar to 'message', but they are used to ask an
      "ok/cancel" or a "yes/no" question.  They return a boolean.