Previous: Common-Lisp-style formatting, Up: Libraries


6.8 Library utilities

Scheme48 provides various miscellaneous library utilities for common general-purpose tasks.

6.8.1 Destructuring

The destructuring structure exports a form for destructuring S-expressions.

— syntax: destructure ((pattern value) ...) body

For each (pattern value) pair, binds every name in pattern to the corresponding location in the S-expression value. For example,

          (destructure (((x . y) (cons 5 3))
                        ((#(a b) c) '(#((1 2) 3) (4 5))))
            body)

binds x to 5, y to 3, a to (1 2), b to 3, and c to (4 5), in body.

6.8.2 Pretty-printing

The pp structure exports a simple pretty-printer.

— procedure: p object [port] –> unspecified
— procedure: pretty-print object port position –> unspecified

P is a convenient alias for pretty-print; it passes 0 for position and the value of (current-output-port) if port is not passed. Pretty-print pretty-prints object to port, using a left margin of position. For example:

          (p '(define (fact n)
                (let loop ((p 1) (c 1))
                  (if (> c n) p (loop (* p c) (+ c 1))))))
              -| (define (fact n)
              -|   (let loop ((p 1) (c 1))
              -|     (if (> c n)
              -|         p
              -|         (loop (* p c) (+ c 1)))))

The pretty-printer is somewhat extensible as well:

— procedure: define-indentation name count –> unspecified

Sets the number of subforms to be indented past name in pretty-printed output to be count. For example:

          (define-indentation 'frobozz 3)
          (p '(frobozz (foo bar baz quux zot) (zot quux baz bar foo)
                       (mumble frotz gargle eek) (froomble zargle hrumph)))
              -| (frobozz (foo bar baz quux zot)
              -|          (zot quux baz bar foo)
              -|          (mumble frotz gargle eek)
              -|   (froomble zargle hrumph))

6.8.3 Strongly connected graph components

The strong structure exports a routine for finding a list of the strongly connected components in a graph.

— procedure: strongly-connected-components vertices to slot set-slot! –> sorted-strong-vertices

Returns the components of a graph containing vertices from the list vertices that are strongly connected, in a reversed topologically sorted list. To should be a procedure of one argument, a vertex, that returns a list of all vertices that have an edge to its argument. Slot & set-slot! should be procedures of one & two arguments, respectively, that access & modify arbitrary slots used by the algorithm. The slot for every vertex should initially be #f before calling strongly-connected-components, and the slots are reverted to #f before strongly-connected-components returns.

6.8.4 Nondeterminism

The nondeterminism structure provides a simple nondeterministic ambivalence operator, like McCarthy's AMB, and a couple utilities atop it, built with Scheme's call-with-current-continuation.

— procedure: with-nondeterminism thunk –> values

Initializes the nondeterminism system and calls thunk; this returns the values thunk returns after then tearing down what was set up.

— syntax: either option ... –> value
— syntax: one-value exp –> value
— syntax: all-values exp –> list

Either evaluates to the value of any one of the options. It is equivalent to McCarthy's AMB. It may return any number of times. One-value returns the only value that exp could produce; it will return only once, although it may actually return any number of values (if exp contains a call to values). All-values returns a list of all of the single values, not multiple values, that exp could nondeterministically evaluate to.

— procedure: fail –> does not return

Signals a nondeterministic failure. This is invalid outside of a with-nondeterminism-protected dynamic extent.

6.8.5 Miscellaneous utilities

The big-util structure exports a variety of miscellaneous utilities.

— procedure: concatenate-symbol elt ... –> symbol

Returns a symbol containing the contents of the sequence elt .... Each elt may be another symbol, a string, or a number. Numbers are converted to strings in base ten.

— procedure: error format-string argument ... –> values (may not return)
— procedure: breakpoint format-string argument ... –> values (may not return)

Error signals an error whose message is formatted by format with the given formatting template string and arguments. Breakpoint signals a breakpoint with a message similarly constructed and causes the command processor to push a new command level.

— procedure: atom? x –> boolean

Returns true if x is not a pair or false if it is.

— procedure: neq? x y –> boolean
— procedure: n= x y –> boolean

Negations of the eq? and = predicates.

— procedure: identity value –> value
— procedure: no-op value –> value

These simply return their arguments. The difference between them is that no-op is guaranteed not to be integrated by the compiler, whereas identity may be.

— procedure: null-list? object –> boolean

Returns #t if object is the null list, returns #f if object is a pair, or signals an error if object is neither the null list nor a pair.

— procedure: reverse! list –> reversed-list

Returns a list containing the reverse elements of list. Note that the original list is not reversed; it becomes garbage. Reverse! simply re-uses its structure.

— procedure: memq? object list –> boolean

Returns #t if object is a member of list, as determined by eq?; or #f if not.

— procedure: first predicate list –> elt or #f
— procedure: any predicate list –> elt or #f

First returns the first element of list that satisfies predicate, or #f if no element does. Any returns an element of list that satisfies predicate. Note that any may choose any element of the list, whereas first explicitly returns the first element that satisfies predicate.

— procedure: any? predicate list –> boolean
— procedure: every? predicate list –> boolean

Any? returns #t if any element of list satisfies predicate, or #f if none do. Every? returns #t if every element of list satisfies predicate, or #f if there exists an element that does not.

— procedure: filter predicate list –> filtered-list
— procedure: filter! predicate list –> filtered-list

These return a list of all elements in list that satisfy predicate. Filter is not allowed to modify list's structure; filter! may, however.

— procedure: filter-map proc list –> list

This is a combination of filter and map. For each element e in list: if (proc e) returns a true value, that true value is collected in the output list. Filter-map does not modify list's structure.

— procedure: remove-duplicates list –> uniquified-list

Returns a unique list of all elements in list; that is, if there were any duplicates of any element e in list, only a single e will occur in the returned list. Remove-duplicates does not modify list's structure.

— procedure: partition-list predicate list –> [satisfied unsatisfied]
— procedure: partition-list! predicate list –> [satisfied unsatisfied]

These return two values: a list of all elements in list that do satisfy predicate and a list of all elements that do not. Partition-list is not allowed to modify list's structure; partition-list! is.

— procedure: delq object list –> list
— procedure: delq! object list –> list

These return a list containing all elements of list except for object. Delq is not allowed to modify list's structure; delq! is.

— procedure: delete predicate list –> list

Returns a list of all elements in list that do not satisfy predicate. Note that, despite the lack of exclamation mark in the name, this may modify list's structure.

— procedure: string->immutable-string string –> immutable-string

Returns an immutable string with string's contents. If string is already immutable, it is returned; otherwise, an immutable copy is returned.

6.8.6 Multiple value binding

The receiving structure exports the receive macro, a convenient syntax atop R5RS's call-with-values.

— syntax: receive formals producer body

Binds the variables in the lambda parameter list formals to the return values of producer in body.

          (receive formals
                   producer
            body)
              ==
          (call-with-values
              (lambda () producer)
            (lambda formals body))

For sequences of multiple value bindings, the mvlet structure exports two convenient macros.

— syntax: mvlet*
— syntax: mvlet

Mvlet* is a multiple-value version of let or a linearly nested version of receive:

          (mvlet* ((formals0 producer0)
                   (formals1 producer1)
                   ...)
            body)
              ==
          (call-with-values
              (lambda () producer0)
            (lambda formals0
              (call-with-values
                  (lambda () producer1)
                (lambda formals1
                  ...body...))))

Mvlet is similar, but each producer is evaluated in an environment where none of the variables in any of the formals is bound, and the order in which each producer expression is evaluated is unspecified.

6.8.7 Object dumper

Scheme48 has a rudimentary object dumper and retriever in the structure dump/restore. It is not a `real' object dumper in the sense that it will not handle cycles in object graphs correctly; it simply performs a recursive descent and will diverge if it reaches a cycle or stop after a recursive depth parameter.

The types of objects that the dumper supports are: several miscellaneous constants ((), #t, #f, & the unspecific token), pairs, vectors, symbols, numbers, strings, characters, and byte vectors.

— procedure: dump object char-writer depth –> unspecified

Dumps object by repeatedly calling char-writer, which must be a procedure that accepts exactly one character argument, on the characters of the serialized representation. If the dumper descends into the object graph whose root is object for more than depth recursions, an ellipsis token is dumped in the place of the vertex at depth.

— procedure: restore char-reader –> object

Restores the object whose serialized components are retrieved by repeatedly calling char-reader, which must be a procedure that accepts zero arguments and returns a character.

6.8.8 Simple time access

The time structure exports a simple facility for accessing time offsets in two different flavours.

— procedure: real-time –> milliseconds

Returns the real time in milliseconds that has passed since some unspecified moment in time.1 Though not suitable for measurements relative to entities outside the Scheme48 image, the real time is useful for measuring time differences within the Scheme image with reasonable precision; for example, thread sleep timing is implemented with this real time primitive.

— procedure: run-time –> ticks

Returns the run time as an integer representing processor clock ticks since the start of the Scheme48 process. This is much less precise than the real time, but it is useful for measuring time actually spent in the Scheme48 process, as opposed to time in general.


Footnotes

[1] In the current implementation on Unix, this moment happens to be the first call to real-time; on Win32, this is the start of the Scheme process.