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

The '`base`' module defines some basic low-level syntactic extensions to MzScheme. It can be used by itself to get these extensions.

This module is intended to be used as a language module (as an initial-import for other modules).

`(#%module-begin ...)` | [syntax]

      'base' is a language module -- it redefines '#%module-begin' to load
      itself for syntax definitions.

`(#%top . id)` | [syntax]

      This special syntax is redefined to make keywords (symbols whose names
      begin with a ":") evaluate to themselves.

`(#%app ...)` | [syntax]

      Redefined so it is possible to apply using dot notation: `(foo x . y)'
      is the same as `(apply foo x y)'.  This is possible only when the last
      (dotted) element is an identifier.

`(define id-or-list ...)` | [syntax]

      The standard 'define' form is modified so defining :keywords is
      forbidden, and if a list is used instead of an identifier name for a
      function then a curried function is defined.
        => (define (((plus x) y) z) (+ x y z))
        => plus
        #<procedure:plus>
        => (plus 5)
        #<procedure:plus:1>
        => ((plus 5) 6)
        #<procedure:plus:2>
        => (((plus 5) 6) 7)
        18
      Note the names of intermediate functions.

      In addition, the following form can be used to define multiple values:
        => (define (values a b) (values 1 2))

`(let ([id-or-list ...] ...) ...)` | [syntax]
`(let* ([id-or-list ...] ...) ...)` | [syntax]
`(letrec ([id-or-list ...] ...) ...)` | [syntax]

      All standard forms of 'let' are redefined so they can generate
      functions using the same shortcut that 'define' allows.  This includes
      the above extension to the standard 'define'.  For example:
        => (let ([((f x) y) (+ x y)]) ((f 1) 2))
        3
      It also includes the 'values' keyword in a similar way to 'define'.
      For example:
        => (let ([(values i o) (make-pipe)]) i)
        #<pipe-input-port>

`(lambda formals body ...)` | [syntax]

      The standard 'lambda' is extended with Lisp-like &-keywords in its
      argument list.  This extension is available using the above short
      syntax.  There is one important difference between these keywords and
      Lisp: some &-keywords are used to access arguments that follow the
      keyword part of the arguments.  This makes it possible to write
      procedures that can be invoked as follows:
        (f <required-args> <optional-args> <keyword-args> <additional-args>)
      (Note: do not use more keywords after the <additional-args>!)

      Available &-keywords are:
      * &optional, &opt, &opts: denote an optional argument, possibly with a
        default value (if the variable is specified as `(var val)').
          => ((lambda (x &optional y [z 3]) (list x y z)) 1)
          (1 #f 3)
          => ((lambda (x &optional y [z 3]) (list x y z)) 1 2 #f)
          (1 2 #f)
      * &keys, &key: a keyword argument -- the variable should be specified
        as 'x' or '(x)' to be initialized by an ':x' keyword, `(x v)' to
        specify a default value 'v', and `(x k v)' to further specify an
        arbitrary keyword 'k'.
          => ((lambda (&key x [y 2] [z :zz 3]) (list x y z)) :x 'x :zz 'z)
          (x 2 z)
        Note that keyword values take precedence on the left, and that
        keywords are not verified:
          => ((lambda (&key y) y) :y 1 :z 3 :y 2)
          1
      * &rest: a 'rest' argument which behaves exactly like the Scheme dot
        formal parameter (actually a synonym for it: can't use both).  Note
        that in case of optional arguments, the rest variable holds any
        arguments that were not used for defaults, but using keys doesn't
        change its value.  For example:
          => ((lambda (x &rest r) r) 1 2 3)
          (2 3)
          => ((lambda (x &optional y &rest r) r) 1)
          ()
          => ((lambda (x &optional y &rest r) r) 1 2 3)
          (3)
          => ((lambda (x &optional y . r) r) 1 2 3)
          (3)
          => ((lambda (x &key y &rest r) (list y r)) 1 :y 2 3 4)
          (2 (:y 2 3 4))
          => ((lambda (x &key y &rest r) (list y r)) 1 :y 2 3 4 5)
          (2 (:y 2 3 4 5))
        Note that the last two examples indicate that there is no error if
        the given argument list is not balanced.
      * &rest-keys: similar to '&rest', but all specified keys are removed
        with their values.
          => ((lambda (x &key y &rest r) r) 1 :x 2 :y 3)
          (:x 2 :y 3)
          => ((lambda (x &key y &rest-keys r) r) 1 :x 2 :y 3)
          (:x 2)
      * &body: similar to '&rest-keys', but all key/values are removed one
        by one until a non-key is encountered.  (Warning: this is *not* the
        same as in Common Lisp!)
          => ((lambda (x &key y &body r) r) 1 :x 2 :y 3)
          ()
          => ((lambda (x &key y &body r) r) 1 :x 2 :y 3 5 6)
          (5 6)
      * &all-keys: the list of all keys+vals, without a trailing body.
          => ((lambda (&keys x y &all-keys r) r) :x 1 :z 2 3 4)
          (:x 1 :z 2)
      * &other-keys: the list of unprocessed keys+vals, without a trailing
        body.
          => ((lambda (&keys x y &other-keys r) r) :x 1 :z 2 3 4)
          (:z 2)

      Finally, here is an example where all &rest-like arguments are
      different:
        => ((lambda (&keys x y
                     &rest r
                     &rest-keys rk
                     &body b
                     &all-keys ak
                     &other-keys ok)
              (list r rk b ak ok))
            :z 1 :x 2 2 3 4)
        ((:z 1 :x 2 2 3 4) (:z 1 2 3 4) (2 3 4) (:z 1 :x 2) (:z 1))
      Note that the following invariants hold:
      * rest = (append all-keys body)
      * rest-keys = (append other-keys body)

`(keyword? x)` | [procedure]

      A predicate for keyword symbols (symbols that begin with a ":").
      (Note: this is different from MzScheme's keywords!)

`(syntax-keyword? x)` | [procedure]

      Similar to 'keyword?' but also works for an identifier (a syntax
      object) that contains a keyword.

`(keyword->string k)` | [procedure]
`(string->keyword s)` | [procedure]

      Convert a Swindle keyword to a string and back.

`(getarg args keyword [not-found])` | [procedure]

      Searches the given list of arguments for a value matched with the
      given keyword.  Similar to CL's 'getf', except no error checking is
      done for an unbalanced list.  In case no value is found, the optional
      default value can be used -- this can be either a thunk, a promise, or
      any other value that will be used as is.  For a repeated keyword the
      leftmost occurrence is used.

`(syntax-getarg syntax-args keyword [not-found])` | [procedure]

      Similar to 'getarg' above, but the input is a syntax object of a
      keyword-value list.

`(getargs initargs keyword)` | [procedure]

      The same as 'getarg' but return the list of all key values matched --
      no need for a default value.  The result is in the same order as in
      the input.

`(keys/args args)` | [procedure]

      The given argument list is scanned and split at the point where there
      are no more keyword-values, and the two parts are returned as two
      values.
        => (keys/args '(:a 1 :b 2 3 4 5))
        (:a 1 :b 2)
        (3 4 5)

`(filter-out-keys outs args)` | [procedure]

      The keywords specified in the outs argument, with their matching
      values are filtered out of the second arguments.