#
Chapter 16
`etc.ss`: Useful Procedures and Syntax

To load: `(require (lib "etc.ss"))`

`(`begin-lifted` `expr `···`1`)` S Y N T A X

Lifts the `expr`s so that they are evaluated once at the ``top level'' of the current context, and the result of the last `expr` is used for every evaluation of the `begin-lifted` form.

When this form is used as a run-time expression within a module, the ``top level'' corresponds to the module's top level, so that each `expr` is evaluated once for each invocation of the module. When it is used as a run-time expression outside of a module, the ``top level'' corresponds to the true top level. When this form is used in a `define-syntax`, `letrec-syntax`, etc. binding, the ``top level'' corresponds to the beginning of the binding's right-hand side. Other forms may redefine ``top level'' (using `local-expand/capture-lifts`) for the expressions that they enclose.

`(`begin-with-definitions` `defn-or-expr `···``)` S Y N T A X

Supports a mixture of expressions and mutually recursive definitions, much like a `module` body. Unlike in a `module`, however, syntax definitions cannot be used to generate other immediate definitions (though they can be used for expressions).

The result of the `begin-with-definitions` form is the result of the last `defn-or-expr` if it is an expression, void otherwise. If no `defn-or-expr` is provided (after flattening `begin` forms), the result is void.

`(boolean=?``` `bool1 bool2``)` P R O C E D U R E

Returns `#t` if `bool1` and `bool2` are both `#t` or both `#f`, and returns `#f` otherwise. If either `bool1` or `bool2` is not a Boolean, the `exn:fail:contract` exception is raised.

`(build-list``` `n f``)` P R O C E D U R E

Creates a list of `n` elements by applying `f` to the integers from `0` to `n` `-` `1` in order, where `n` is a non-negative integer. If `r` is the resulting list, `(`list-ref` r i)` is `(`f` `i`)`.

`(build-string``` `n f``)` P R O C E D U R E

Creates a string of length `n` by applying `f` to the integers from `0` to `n` `-` `1` in order, where `n` is a non-negative integer and `f` returns a character for the `n` invocations. If `r` is the resulting string, `(`string-ref` r i)` is `(`f` `i`)`.

`(build-vector``` `n f``)` P R O C E D U R E

Creates a vector of `n` elements by applying `f` to the integers from `0` to `n` `-` `1` in order, where `n` is a non-negative integer. If `r` is the resulting vector, `(`vector-ref` r i)` is `(`f` `i`)`.

`(compose``` `f``` `···`1`)` P R O C E D U R E

Returns a procedure that composes the given functions, applying the last `f` first and the first `f` last. The composed functions can consume and produce any number of values, as long as each function produces as many values as the preceding function consumes.

For example, `(compose `f` `g`)` returns the equivalent of `(lambda l (`call-with-values` (lambda () (`apply` g l)) f))`.

`(`define-syntax-set` ``(`identifier `···``)` defn `···``)` S Y N T A X

This form is similar to `define-syntaxes`, but instead of a single body expression, a sequence of definitions follows the sequence of defined identifiers. For each `identifier`, the `defn`s should include a definition for ``identifier`/proc`. The value for ``identifier`/proc` is used as the (expansion-time) value for `identifier`.

The `define-syntax-set` form is especially useful for defining a set of syntax transformers that share helper functions.

Example:

    (define-syntax-set (let-current-continuation let-current-escape-continuation)
      (define (mk call-id)
         (lambda (stx)
           (syntax-case stx ()
             [(_ id body1 body ...)
              (with-syntax ([call call-id])
                (syntax (call (lambda (id) body1 body ...))))])))
      (define let-current-continuation/proc (mk (quote-syntax call/cc)))
      (define let-current-escape-continuation/proc (mk (quote-syntax call/ec))))

`(`evcase` `key-expr `(`value-expr body-expr `···``)` `···`1`)` S Y N T A X

The `evcase` form is similar to `case`, except that expressions are provided in each clause instead of a sequence of data. After `key-expr` is evaluated, each `value-expr` is evaluated until a value is found that is `eqv?` to the key value; when a matching value is found, the corresponding `body-expr`s are evaluated and the value(s) for the last is the result of the entire `evcase` expression.

A `value-expr` can be the special identifier `else`. This identifier is recognized as in `case` (see section 2.3 in PLT MzScheme: Language Manual).

`false` B O O L E A N

Boolean false.

`(identity``` `v``)` P R O C E D U R E

Returns `v`.

`(`let+` `clause body-expr `···`1`)` S Y N T A X

A new binding construct that specifies scoping on a per-binding basis instead of a per-expression basis. It helps eliminate rightward-drift in programs. It looks similar to `let`, except each clause has an additional keyword tag before the binding variables.

Each `clause` has one of the following forms:

- `(`val` target expr)` binds `target` non-recursively to `expr`.

- `(rec target expr)` binds `target` recursively to `expr`.

- `(`vals` (target expr) `···`)` the `target`s are bound to the `expr`s. The environment of the `expr`s is the environment active before this clause.

- `(`recs` (variable expr) `···`)` the `targets`s are bound to the `expr`s. The environment of the `expr`s includes all of the `targets`s.

- `(_ expr `···`)` evaluates the `expr`s without binding any variables.

The clauses bind left-to-right. Each `target` above can either be an identifier or `(`values` variable `···`)`. In the latter case, multiple values returned by the corresponding expression are bound to the multiple variables.

Examples:

    (let+ ([val (values x y) (values 1 2)])
       (list x y)) ; => '(1 2)

    (let ([x 1])
       (let+ ([val x 3]
              [val y x])
          y)) ; => 3

`(`local` ``(`definition `···``)` body-expr `···`1`)` S Y N T A X

This is a binding form similar to `letrec`, except that each `definition` is a `define-values` expression (after partial macro expansion). The `body-expr`s are evaluated in the lexical scope of these definitions.

`(loop-until``` `start done? next f``)` P R O C E D U R E

Repeatedly invokes the `f` procedure until the `done?` procedure returns `#t`. The procedure is best described by its implementation:

    (define loop-until
      (lambda (start done? next f)
        (let loop ([i start])
          (unless (done? i)
            (f i)
            (loop (next i))))))

`(namespace-defined?``` `symbol``)` P R O C E D U R E

Returns `#t` if ``namespace-variable-value`` would return a value for `symbol`, `#f` otherwise. See section 8.2 in PLT MzScheme: Language Manual for further information.

`(`nand` `expr `···``)` S Y N T A X

Returns `(`not` (and expr `···`))`.

`(`nor` `expr `···``)` S Y N T A X

Returns `(`not` (or expr `···`))`.

`(`opt-lambda` `formals body-expr `···`1`)` S Y N T A X

The `opt-lambda` form is like `lambda`, except that default values are assigned to arguments (C++-style). Default values are defined in the `formals` list by replacing each `variable` by `[`variable` `default-value-expression`]`. If a variable has a default value expression, then all (non-aggregate) variables after it must have default value expressions. A final aggregate variable can be used as in `lambda`, but it cannot be given a default value. Each default value expression is evaluated only if it is needed. The environment of each default value expression includes the preceding arguments.

For example:

    (define f
      (opt-lambda (a [b (add1 a)] . c)
         ...))

In the example, `f` is a procedure which takes at least one argument. If a second argument is specified, it is the value of `b`, otherwise `b` is `(`add1` a)`. If more than two arguments are specified, then the extra arguments are placed in a new list that is the value of `c`.

See also section 22 for a library that generalizes both optional and keyword arguments.

`(`recur` `name bindings body-expr `···`1`)` S Y N T A X

This is equivalent to a named `let`: `(let name bindings body-expr `···`1)`.

`(`rec` `name value-expr`)` S Y N T A X

This is equivalent to a `letrec` expression that returns its binding: `(letrec ((name value-expr)) name)`.

`(symbol=?``` `symbol1 symbol2``)` P R O C E D U R E

Returns `#t` if `symbol1` and `symbol2` are equivalent (as determined by `eq?`), `#f` otherwise. If either `symbol1` or `symbol2` is not a symbol, the `exn:fail:contract` exception is raised.

`(`this-expression-source-directory`)` S Y N T A X

Expands to an expression that evaluates to the name of the directory of the file containing the source expression. The source expression's file is determined through source location information associated with the syntax if it is present. Otherwise, `current-load-relative-directory` is used if it is not `#f`, and `current-directory` is used if all else fails. The expression is a simple `(bytes->path #"...")`, unless the directory is in the PLT home, which will make an expression that uses ``plthome`' to get the PLT home path determined at runtime, therefore not hard-wiring the path to the resulting syntax.

`(`this-expression-file-name`)` S Y N T A X

Expands to an expression that evaluates to the file name of the source expression. The source expression's file name is determined through source location information associated with the syntax if it is present. If this information is missing, or is not a path (e.g., for a standard-input expression), then `#f` will be used instead.

`true` B O O L E A N

Boolean true.

`(`hash-table` `'flag `...`(key value) `...``)` S Y N T A X

This creates a new hash-table providing the quoted flags (if any) to ``make-hash-table``, and make each of the keys map to the corresponding values. (Flags must be specified by a quoted form.)