A batteries-included extended standard library for seven R7RS Scheme dialects.
A kitchen-sink utility library for several R7RS Scheme dialects.
This library is unfinished and under heavy development. It's optimized for the needs of a few related projects I'm working on, mostly programming language interpreters and compilers.
To use this library, drop this repository in a schemepunk
directory in your
project, ideally as a Git submodule. The shell scripts in scripts
can run unit
tests or Scheme applications in all of Schemepunk's supported Scheme dialects,
and they know how to find and include .sld
library dependencies, even in
Schemes that don't natively support this.
* Chicken requires these eggs: r7rs
, utf8
, box
, srfi-41
, srfi-69
,
srfi-99
, srfi-113
, srfi-128
, srfi-133
, and ioctl
. (ioctl
is only
required on Unix-based OSes.)
Schemepunk can also be built as a Chicken egg. Just run chicken-install
(possibly with -sudo
) in the repo's root directory.
(schemepunk box)
- Boxes
(schemepunk btree)
- Persistent B-trees
(schemepunk command)
- Command-line argument parsing
(schemepunk comparator)
- Comparators
(schemepunk datalog)
- Logic programming (WIP)
(schemepunk flexvector)
- Flexvectors (dynamic arrays)
(schemepunk function)
- Functional programming utilities
(schemepunk generator)
- Generators and accumulators
(schemepunk hash-table)
- Hash tables
(schemepunk hook)
- Hooks
(schemepunk json)
- JSON
(schemepunk list)
- List utilities
(schemepunk mapping)
- Persistent mappings
(schemepunk multimap)
- Multimaps
(schemepunk path)
- File path utilities
(schemepunk random)
- Random number generation
(schemepunk set)
- Sets and bags
(schemepunk show)
- Monadic text formatting
(schemepunk sort)
- Sorting
(schemepunk stream)
- Streams
(schemepunk string)
- String utilities
(schemepunk syntax)
- Utility macros
(schemepunk term-colors)
- ANSI terminal colors
(schemepunk test)
- Unit test framework
(schemepunk vector)
- Vector library
(schemepunk box)
Polyfilled alias for SRFI 111 (Boxes). Exports one additional procedure:
(update-box! <box> <proc>)
is equivalent to
(set-box! <box> (<proc> (unbox <box>)))
.(schemepunk btree)
An original implementation of persistent B-trees, used to implement (schemepunk mapping)
on all Schemes except Gauche¹.
Schemepunk's B-tree mappings are frequently 2-3 times faster than the
red-black-tree reference implementation of SRFI 146, and significantly faster
when constructing large mappings. This library includes linear-update
!
-suffixed mutation procedures, for yet another performance boost.
You usually want to use this module through (schemepunk mapping)
, but, if you
want to use the B-tree data structure directly, this module provides these
low-level procedures:
(btree <comparator> <max-size>)
(btree? <btree>)
(btree-key-comparator <btree>)
(btree-empty? <btree>)
(btree-copy <btree>)
(btree-ref <key> <value> <failure-proc>)
(failure-proc
is optional)
(btree-set <btree> <key> <value>)
(btree-set! <btree> <key> <value>)
(btree-delete <btree> <key>)
(btree-delete! <btree> <key>)
(btree-pop <btree> <key>)
(returns two values: (key . value)
and modified btree)
(btree-pop! <btree> <key>)
(returns one value: (key . value)
)
(btree-fold <fn> <seed> <btree>)
(btree-fold-right <fn> <seed> <btree>)
(alist->btree <alist> <comparator> <max-size>)
(btree->alist <btree>)
(btree-subset? <value-comparator> <btree1> <btree2>)
(btree=? <value-comparator> <btree1> <btree2>)
(btree<? <value-comparator> <btree1> <btree2>)
(btree-hash <value-comparator> <btree>)
(make-btree-comparator <value-comparator>)
btree-comparator
¹ B-trees are faster than most Schemes' SRFI 146, but Gauche's <tree-map>
is
usually even faster.
(schemepunk command)
A command-line argument parser, loosely based on Chibi Scheme's
(chibi app)
. The parser procedures take app specifications,
which are nested alists. For example, the zoo demo from the (chibi app)
documentation can be written like this for (schemepunk command)
:
'((name "Zookeeper Application")
(doc "Example application from (chibi app) documentation, adapted for \
(schemepunk command).")
(copyright "Copyright (c) 2020")
(options
(animals
(type (list symbol))
(doc "list of animals to act on (default all)"))
(lions
(short #\l)
(doc "also apply the action to lions")))
(commands
(feed
(short-doc "feed the animals")
(doc-args <animals> ...))
(wash
(short-doc "wash the animals")
(doc-args <animals> ...)
(options (soap)))
(help
(short-doc "print help")))
(require-command #t))
(schemepunk command)
supports both -
short options and --
long options.
Short options can be grouped: -xyz
= -x -y -z
. Values after option names can
follow either a space or =
. Git-style commands, with their own documentation
and option lists, are also supported.
(run-application <spec> <command-line> <proc>)
parses the list of
command-line arguments <command-line>
using the specification <spec>
.
The first element of <command-line>
should be the executable name.
If parsing is successful, <proc>
is tail-called with five arguments:
options
, an alist of the -
or --
options passed to the appargs
, a list of all non-option and non-command arguments passed to the
app, as stringscommand
, the command name passed to the app, or #f
if there is no
commandcommand-options
, an alist of all options that occurred after the command
namecommand-args
, a list of all non-option arguments that occurred after the
command name, as stringsIf parsing fails, a usage message is printed to (current-error-port)
, and
then Scheme is terminated with (exit 1)
.
(parse-app <spec> <command-line>)
parses the list of command-line arguments
<command-line>
using the specification <spec>
, and returns five values,
corresponding to the five arguments passed to run-application
's <proc>
. If
parsing fails, it will raise an error object for which command-error?
is
#t
.
(app-usage <spec> <command-line>)
is a (schemepunk show)
formatter that
prints a usage message for the app specification <spec>
. The executable name
is taken from the first element of the list <command-line>
.
(command-usage <spec> <command> <command-line>)
is a (schemepunk show)
formatter that prints a usage message for the command <command>
in the app
specification <spec>
. The executable name is taken from the first element of
the list <command-line>
.
app-help
and command-help
are like app-usage
and command-usage
, but
also include name
, doc
, and copyright
if they are present in the
specification.
(command-error? <datum>)
is a type predicate for the error objects raised by
parse-app
.
All alist keys are optional; the empty specification '()
is valid but has no
documentation and accepts no options.
name
- name of the application, displayed at the start of the app's help
textdoc
- documentation paragraph, displayed at the start of the app's help textdoc-args
- symbols or strings that describe the app's arguments in usage
text; e.g., <input-file> "[<output-file>]"
copyright
- copyright message displayed at bottom of help textoptions
- alist of options for the app; each option's key is also its
default long option namecommands
- alist of commands for the app; each command's key is also its
namerequire-command
- if #t
, app exits with an error if no command is provideddefault-help-option
- if #t
, an option is added with long name --help
and short name -h
that, if present, causes run-application
to print the
app's help text and exitdefault-help-command
- if #t
, a command named help
is added that, if
selected and passed a command name as its only argument, causes
run-application
to display that command's help text and exittype
- data type of the option's value, defaults to boolean
; options are
boolean
, symbol
, char
, string
, integer
, real
, sexp
, and
(list <type>)
long
- long option aliases for this option (symbols or strings)short
- short option aliases for this option (chars)doc
- description of this option, displayed in usage textdoc-value
- name of the option's value, displayed in usage text, defaults to
value of type
short-doc
- documentation shown in the app's usage textdoc
- longer documentation shown in the command's usage textdoc-args
- symbols or strings that describe the command's arguments in usage
text; e.g., <input-file> "[<output-file>]"
options
- alist of options for the command; each option's key is also its
default long option name(schemepunk comparator)
Polyfilled alias for SRFI 128 (Comparators) with SRFI 162 (Comparators sublibrary) extensions. These comparators are used by all of Schemepunk's ordered data structures: sets, bags, hash tables, mappings, and multimaps.
In addition to SRFIs 128 and 162, this module exports several extra procedures, macros, and comparators:
symbol-comparator
is a default comparator for symbols.
number-comparator
is a default comparator for numbers that is more general
than SRFI 162's real-comparator
.
fixnum-comparator
is a default comparator for fixnums (small integers).
(make-sum-comparator <comparators>…)
creates a comparator for the sum type
of the types represented by each comparator in <comparators>
. For example,
(make-sum-comparator boolean-comparator number-comparator string-comparator)
returns a comparator for values that may be either booleans, numbers, or
strings.
(hash-lambda (<param>) <body>…)
is equivalent to
(lambda (<param>) <body>…)
, except that it takes and ignores an optional
second argument. This macro should be used to define hash functions. Some
Schemes' SRFI 128 or SRFI 69 implementations expect hash functions to take one
parameter, others expect two, and this is the only way to write hash functions
that are compatible with all of them.
(identity-hash <x>)
is a reference-identity-based hash function, used by
eq-comparator
. It should always return different hashes for values that are
not eq?
. This is a primitive operator that cannot be implemented portably,
so it is always an alias for the host Scheme's identity hash function.
(identity<? <x> <y>)
is an identity-based ordering function, used by
eq-comparator
. It compares the identity-hash
of <x>
and <y>
.
(schemepunk datalog)
WIP simple Datalog logic programming library. Still unfinished, not much to see here. So far, it supports semi-naive evaluation and stratified negation.
(schemepunk flexvector)
Polyfilled alias for SRFI 214 (Flexvectors). No additional exports.
(schemepunk function)
Combinators commonly used in functional languages like Haskell or ML.
(identity <x>)
returns <x>
.
(const <x>)
returns a procedure that takes one argument, ignores it, and
returns <x>
.
(flip <f>)
takes a procedure of two arguments <f>
, and returns a new
procedure (g x y)
that calls (<f> y x)
.
(compose <fs>…)
composes procedures right-to-left: (compose f g)
returns
a procedure (composed x)
that calls (f (g x))
.
(bind <fs>…)
composes procedures left-to-right: (bind f g)
returns a
procedure (composed x)
that calls (g (f x))
.
(complement <pred?>)
takes a predicate <pred?>
and returns its complement
(a predicate that always returns the opposite boolean value).
(schemepunk generator)
Polyfilled alias for SRFI 158 (Generators and Accumulators). Exports one additional procedure:
(gfork <gen>)
returns two values, both of which are generators that produce
the same sequence of values as <gen>
.(schemepunk hash-table)
Polyfilled alias for SRFI 125 (Intermediate Hash Tables). No
additional exports. Uses comparators from (schemepunk comparator)
.
(schemepunk hook)
Polyfilled alias for SRFI 173 (Hooks). No additional exports.
(schemepunk json)
Minimal JSON parser. Can encode and decode JSON to/from a simple Scheme representation:
JSON value | Scheme representation |
---|---|
null |
The symbol null |
true |
The symbol true |
false |
The symbol false |
3.14 |
3.14 |
"foo" |
"foo" |
[1, 2, 3] |
#(1 2 3) |
{} |
() |
{"a": 1, "b": 2} |
(("a" . 1) ("b" . 2)) |
(read-json <port>)
reads one JSON value from a port and returns it. <port>
is optional.
(write-json <json> <port>)
writes one JSON value to a port. Anything that
is not a valid Scheme representation of JSON will be written as <NOT JSON>
.
<port>
is optional.
string->json
and json->string
convert JSON strings to/from their Scheme
representations.
A simple event-based parser is also available, for performance:
(make-json-context)
creates a new context object.
(read-json-event <context> <port>)
reads one JSON event from a port. It
returns two values: (event payload)
, where event
is the event type and
payload
is an optional value. It takes a context object, which keeps track
of nesting and object keys. <port>
is optional.
Event | Payload |
---|---|
null |
#f |
boolean |
Value (#t or #f ) |
number |
Value (number) |
string |
Value (string) |
array-start |
#f |
array-end |
#f |
object-start |
#f |
key |
Key name (string) |
object-end |
#f |
error |
Error message (string) |
(schemepunk list)
Alias for SRFI 1 (List Library). Because all supported Schemes include this SRFI, there is no polyfill.
In addition to SRFI 1, this module exports several extra procedures:
(snoc <list> <elem>)
is a reverse cons
; it constructs a list by appending
elem
to the end of list
.
(map-with-index <fn> <list>)
is like map
, but it expects fn
to take two
arguments. The second argument is the index of the list item.
(intercalate <delimiter> <list>)
constructs a new list by inserting
<delimiter>
between each pair of elements in <list>
.
(list-gen <fn>)
is a generator-style unfold. fn
is a lambda that takes
two arguments, usually named yield
and done
. (yield x)
adds x
to the
end of the list being constructed, then recursively calls fn
. done
is the
current list (not a procedure!), and should be returned to end the recursion.
For example, this reads characters from (current-input-port)
into a list
until EOF:
(list-gen (lambda (yield done)
(let ((ch (read-char)))
(if (eof-object? ch) done (yield ch)))))
(fold-by-pairs <fn> <seed> <list>)
is like fold
, but reads list
two
elements at a time. It calls fn
with three arguments. It raises an error if
list
does not contain an even number of elements.
(fold-right-by-pairs <fn> <seed> <list>)
is fold-by-pairs
in reverse.
(topological-sort <dependencies>)
sorts a list of dependencies in dependency
order.
dependencies
is an alist, in which the car of each element is a dependency,
and the cdr of each element is a list of its dependencies, each of which must
be the car of another element. The list must contain no dependency cycles.
(schemepunk mapping)
Polyfilled alias for SRFI 146 (Mappings). No additional exports.
Uses comparators from (schemepunk comparator)
. Does not include (srfi 146 hash)
.
All Schemes except Gauche use Schemepunk's implementation, which is based on
(schemepunk btree)
. Gauche's (srfi 146)
is native and faster than
(schemepunk btree)
, so it is used when possible.
(schemepunk multimap)
Mappings from one key to a set of values, based on (schemepunk mapping)
and
(schemepunk set)
. Uses comparators from (schemepunk comparator)
.
(multimap <key-comparator> <value-comparator>)
constructs a new, empty
multimap. A multimap requires comparators for both keys and values.(multimap-copy <mmap>)
returns a distinct copy of <mmap>
.(multimap? <datum>)
is the type predicate for multimaps.(multimap-key-comparator <mmap>)
and (multimap-value-comparator <mmap>)
return the comparators used by <mmap>
.(multimap-ref <mmap> <key>)
returns the set of values for <key>
in
<mmap>
.(multimap->mapping <mmap>)
returns the underlying mapping of <mmap>
. Its
keys are the same as <mmap>
's, and its values are sets.(multimap-contains? <mmap> <value>)
returns #t
if <mmap>
contains the
value <value>
in any key's value set, and #f
otherwise.(multimap-contains-key? <mmap> <key>)
returns #t
if <mmap>
contains the
key <key>
, #f
otherwise.(multimap-keys <mmap>)
returns a list of the keys in <mmap>
.(multimap-values <mmap>)
returns a list of all values in all value sets in
<mmap>
.(multimap-value-sets <mmap>)
returns a list of the value sets in <mmap>
.(multimap-key-count <mmap>)
returns the number of keys in <mmap>
.(multimap-value-count <mmap>)
returns the total number of values in all
value sets in <mmap>
.(multimap-empty? <mmap>)
returns #t
if <mmap>
is empty, #f
otherwise.(multimap-adjoin <mmap> <key> <value>)
and
(multimap-adjoin! <mmap> <key> <value>)
return a new multimap with <value>
added to the set of values for <key>
in <mmap>
. multimap-adjoin!
mutates
<mmap>
in-place before returning it.(multimap-adjoin-set <mmap> <key> <vals>)
and
(multimap-adjoin-set! <mmap> <key> <vals>)
return a new multimap with all
values in the set <vals>
added to the set of values for <key>
in <mmap>
.
multimap-adjoin-set!
mutates <mmap>
in-place before returning it.(multimap-delete-key <mmap> <key>)
and (multimap-delete-key! <mmap> <key>)
return a new multimap with all values for <key>
in <mmap>
removed.
multimap-delete-key!
mutates <mmap>
in-place before returning it.(multimap-delete-value <mmap> <key> <value>)
and
(multimap-delete-value! <mmap> <key> <value>)
return a new multimap with
<value>
removed from the set of values for <key>
in <mmap>
.
multimap-delete-value!
mutates <mmap>
in-place before returning it.(multimap-clear! <mmap>)
mutates <mmap>
by removing all keys and values.(multimap-union <lhs> <rhs>)
and (multimap-union! <lhs> <rhs>)
return a
multimap containing all key/value pairs from both <lhs>
and <rhs>
. If both
multimaps contain the same key, the returned multimap will contain the union
of both maps' value sets for that key. multimap-union!
mutates <lhs>
in-place before returning it.(multimap-difference <lhs> <rhs>)
returns a multimap that is the result of
removing all key/value pairs in <rhs>
from <lhs>
.(schemepunk path)
Procedures for manipulating file path strings. These use the path format of the current OS; there are separate implementations for Windows and Unix-like OSes.
(current-directory)
returns the current working directory.(path-join <path> <suffix>…)
appends each <suffix>
to the root path
<path>
using the OS path separator.(path-normalize <path>)
converts <path>
to an equivalent, normalized form
by removing any unnecessary .
or ..
elements, correcting path separators,
and (on Windows) adding a missing drive name.(path-root? <path>)
returns whether <path>
is an absolute root path (e.g.,
/
on Unix or C:\
on Windows).(path-directory <path>)
returns the path of the parent directory of
<path>
.(path-strip-directory <path>)
returns the final path element of <path>
.(path-absolute? <path>)
returns whether <path>
is an absolute path.(path-relative? <path>)
returns whether <path>
is a relative path.(relative-path->absolute-path <path>)
converts a relative path to an
absolute path, assuming that the path is relative to (current-directory)
.(schemepunk random)
Generates random numbers.
(random-integer <max>)
generates a random exact integer between 0
and
<max>
, exclusive.(random-real)
generates a random real number between 0
and 1
.(schemepunk set)
Polyfilled alias for SRFI 113 (Sets and Bags). No additional exports.
Uses comparators from (schemepunk comparator)
.
(schemepunk show)
A full-featured, original implementation of SRFI 166 (Monadic Text Formatting). Supports colorized pretty-printing, Unicode-aware alignment and truncation, columns, tables, and more.
This implementation is based on SRFI 158 generators. A formatter is a procedure
that takes a mapping of state variables and returns a generator of spans. A span
is a record containing a string, a type (text
, whitespace
, or newline
) and
a color.
Schemepunk's SRFI 166 includes several additional operators and submodules. The additional exports, grouped by submodule, are as follows:
(schemepunk show base)
(call-with-output-generator <fmt> <proc>)
is like call-with-output
, but
passes a generator to <proc>
instead of a string.(schemepunk show color)
Includes ANSI light colors: as-light-red
, as-light-blue
, as-light-green
,
as-light-cyan
, as-light-yellow
, as-light-magenta
, as-light-white
,
as-light-black
, and as-gray
(alias for as-light-black
).
(schemepunk show columnar)
(boxed <fmts>…)
returns a formatter that draws a box around <fmts>
using
box drawing characters. boxed/double
and boxed/ascii
are variants that
draw a double-line box and an ASCII-only box.
(boxed/custom <color> <h> <v> <nw> <ne> <sw> <se> <fmts>…)
is the box
drawing formatter used by boxed
.
<color>
is a procedure that takes a formatter and returns a procedure.
It is used to apply a color to the box outline. For example, if <color>
is as-red
, the box outline will be red. If the box should not be
colored, <color>
should be each
.<h>
and <v>
are the horizontal and vertical line characters used to
draw the box.<nw>
, <ne>
, <sw>
, and <se>
are the corner characters used to draw
the box. They are the top-left, top-right, bottom-left, and bottom-right
corners, respectively.(collapsed-if-one-line <fmts>…)
returns a formatter that prints <fmts>
with all adjacent whitespace collapsed to single spaces, as in wrapped
, if
and only if the entire collapsed string would fit in a single line. Otherwise,
it prints <fmts>
unchanged.
(schemepunk show pretty)
pretty-json
and pretty-json-color
are equivalents to pretty
and
pretty-color
for (schemepunk json)
-compatible JSON data structures. They
print JSON.
indent-size
is a state variable for the number of spaces in a single
pretty-printing indentation level. Defaults to 2
.
(schemepunk show debug)
A simple interface to (schemepunk show pretty)
for print-statement debugging.
(write-debug <datum>)
prints <datum>
to (current-output-port)
using
pretty-color
, then prints a newline.
(write-debug-json <json>)
prints <json>
to (current-output-port)
using
pretty-json-color
, then prints a newline.
(schemepunk show report)
Formatters for detailed error reports, similar to the error reports in languages
like Rust and Elm. (schemepunk test)
uses this to print test errors.
(reported <title> <fmts>…)
is a formatter that prints a header line with
<title>
embedded into it, followed by <fmts>
.
report-line
is a formatter that prints a single horizontal line the width of
width
, colored to match reported
's headers. Use this at the end of a
sequence of reports.
(wrapped/blocks <fmts>…)
is a variant of wrapped
that handles newlines in
subformatters. If a non-string formatter in <fmts>
contains a newline or is
longer than 2/3 of width
, that formatter is broken out into its own
paragraph, without wrapping, with two newlines above and below it.
Can be used in reports to include pretty-printed Scheme data in wrapped text blocks; the Scheme data will appear as either inline code or standalone code blocks, depending on its size.
(code-snapshot <filename> <source> <line-numbers?> <annotations>…)
prints a
snippet of the string or formatter <source>
, adjusted to fit within the
terminal, with annotations pointing to specific lines and columns. It can
print line-and-column error traces with multiple messages, in the style of
Rust:
<annotations>
is composed of one or more five-element lists:
(<line> <start-col> <end-col> <color> <message>)
. <line>
is the 0-based
line of the annotation, and <start-col>
-<end-col>
are the 0-based column
range of the annotation. <color>
is a color formatter procedure, like
as-red
, and should be each
if the annotation is not colored. <message>
is the annotation message itself, and can be a string or #f
. If
<message>
is #f
, the annotation will be an underline with no message.
(schemepunk show span)
Defines the span data structure. Formatters return generators of spans. Spans
include color data that is not part of their text content. They can also be
marked as whitespace or newlines, which speeds up operations like wrapped
and
is used by the pretty-printing indentation algorithm.
(span? <datum>)
is a type predicate for spans.
(span-type <span>)
returns the type of <span>
(text
, whitespace
, or
newline
).
(span-text <span>)
returns the text content of <span>
as a string.
(span-color <span>)
returns the color of <span>
(a
(schemepunk term-color)
ANSI color, or #f
).
(text-span <str> <color>)
constructs a text
span from a string. <color>
is optional and defaults to #f
.
(whitespace-span <str>)
constructs a whitespace
span from a string.
<str>
is optional and defaults to " "
.
(newline-span <str>)
constructs a newline
span from a string. <str>
is
optional and defaults to the string printed by (newline)
.
(span-map-text <proc> <span>)
returns a copy of <span>
whose text content
is the result of applying <proc>
to (span-text <span>)
.
(span-with-color <span> <color>)
returns a copy of <span>
with the color
<color>
.
(char-generator->span-generator <gen> <word-separator?> <read-ansi-escapes?>)
takes a generator of chars (<gen>
) and returns a generator of spans. Any
#\newline
character becomes a newline
span, any group of characters for
which word-separator?
returns true becomes a whitespace
span, and all
groups of characters between these become text
spans.
<word-separator?>
is an optional predicate and defaults to
char-whitespace?
.<read-ansi-escapes?>
is an optional boolean and defaults to #f
. If it is
#t
, this procedure will check for ANSI escapes in the character stream
and include them in the generated spans as color values.(write-span <span> <port>)
writes the text of <span>
to <port>
, wrapped
in ANSI escapes if the span has a color. <port>
is optional and defaults to
(current-output-port)
.
(schemepunk sort)
Polyfilled alias for SRFI 132 (Sort Libraries). No additional exports.
(schemepunk stream)
Alias for SRFI 41 (Streams). Because all supported Schemes include this SRFI, there is no polyfill. No additional exports.
(schemepunk string)
Polyfilled alias for SRFI 152 (String Library (Reduced)). The polyfill is not a full SRFI 152 implementation; it imports either SRFI 13 or SRFI 130, then fills in the missing SRFI 152 procedures. No additional exports.
Compatibility note: The string<?
and string-ci<?
family of comparison
procedures in (schemepunk string)
do not strictly match the specification.
They are simple reexports of the matching procedures from (scheme base)
and
(scheme char)
, and as such they only accept exactly two arguments. This was
done because, in some Schemes, it is an error to import two different
definitions with the same name. If they were defined according to the
specification, it would be impossible to import (scheme base)
and (schemepunk string)
in the same module without excluding these imports.
(schemepunk syntax)
A collection of utility macros. Includes SRFI 2 (and-let*
), SRFI 8
(receive
), SRFI 26 (cut
and cute
), SRFI 28
(format
), SRFI 145 (assume
), SRFI 156 (is
),
and SRFI 197 (chain
).
λ
is shorthand for lambda
. Parentheses may be omitted for a single
argument name: (λ x (+ x 1))
= (lambda (x) (+ x 1))
. Arguments may contain
destructuring assigments (see match
).
Caution: λ
is not substitutable for lambda
in all situations.
(lambda x …)
takes any numer of arguments, but (λ x …)
takes one.
chain
is similar to Clojure threading macros, but with
_
as an explicit argument marker. This macro is fully defined in
SRFI 197.
(chain x (foo y _) (bar _ z)) ; => (bar (foo y x) z)
chain-lambda
defines a lambda using a chain
pipeline. (chain-lambda (foo y _) (bar _ z))
= (lambda (x) (chain x (foo y _) (bar _ z)))
. λ=>
is
shorthand for chain-lambda
.
(let1 <name> <value> <body>…)
is shorthand for let
with a single
variable.
(if-let <name> <value> <then> <else>)
is a version of if
that assigns the
predicate <value>
to a variable <name>
.
(let/cc <name> <body>…)
is shorthand for
(call/cc (lambda (<name>) <body>…))
.
(match <value> (<pattern> <expr>…)…)
is a hygenic pattern-matching macro,
based on Alex Shinn's match-simple.scm
, which is itself based on Andrew
Wright's match
. It is a portable subset of the functionality of the match
packages in Chibi and Gauche.
It supports only the basic features of (chibi match)
. It is
missing the =>
, @
, $
, =
, ..1
, get!
, and set!
operators, and it
does not support the symbol ...
as an ellipsis operator (use ___
or …
instead).
(match-let ((<pattern> <value>)…) <body>…)
uses the
pattern-matching syntax from match
as destructuring assignment.
Related functions match-let*
, match-let1
, and match-letrec
are also
available.
(match-lambda (<pattern> <expr>…)…)
defines a lambda of one argument
that matches its argument against one or more patterns. matchλ
is an alias.
match-lamda*
matches its entire argument list against the patterns.
(match-guard ((<pattern> <handler>…)…) <expressions>…)
is a guard
form with pattern-matching. It matches the raised error against each
pattern
.
(define+ (<name> <params>… :optional <optional-params>… :rest <rest-param>) <body>…)
is a form of define
that supports destructuring assignment (as in λ
) and
optional parameters. It uses Gauche's syntax for optional and rest parameters.
The :optional
and :rest
sections are optional. Each <optional-param>
may be a symbol or a list (<name> <default>)
. The <params>
and
<rest-param>
sections may be match
patterns.
(schemepunk term-colors)
ANSI escape codes for terminal colors.
(write-in-color <color> <string>)
writes string
to (current-output-port)
,
with the ANSI escape codes to make it appear as color
. The escape codes are
not printed if Schemepunk detects that the current terminal does not support
them; this can be overridden by setting the parameter term-colors-enabled?
to
#t
.
<color>
is a color object, which may be one of:
black
, red
, yellow
, green
, blue
, cyan
, magenta
,
white
, light-black
(or gray
), light-red
, light-yellow
,
light-green
, light-blue
, light-cyan
, light-magenta
, and light-white
.bold-black
, bold-red
, bold-yellow
, bold-green
,
bold-blue
, bold-cyan
, bold-magenta
, and bold-white
. Depending on your
terminal, these may look exactly like the light colors, or they may be
rendered in a bold font.Colors can also be constructed with make-color
, which takes any combination of
SGR parameters from these groups:
fg-black
, fg-red
, fg-light-red
, etc.bg-black
, bg-red
, etc.attr-bold
, attr-italic
, attr-negative
, or attr-underline
.Order does not matter, and any or all of these can be omitted. (make-color)
with no arguments is the color reset escape code, also available as reset
.
If your terminal supports 256 colors or true color, (schemepunk term-color)
can also generate those escape codes, using (make-8-bit-color <r> <g> <b>)
and
(make-24-bit-color <r> <g> <b>)
. 8-bit RGB values range from 0-5; 24-bit RGB
values range from 0-255. Background colors are also available via
make-8-bit-color/bg
and make-24-bit-color/bg
.
For more fine-grained control, (write-color <color>)
writes a single ANSI
escape code. Make sure to reset with (reset-color)
after writing!
(schemepunk test)
A unit test framework modeled after Javascript's Mocha. Although its preferred API differs from SRFI 64, it includes compatibility macros that allow it to run SRFI 64 tests without modifications.
Test suites are defined as (test-group <name> <tests>…)
, where <tests>
is
one or more (test <name> <expressions>…)
clauses. Test suite files have the
.test.scm
extension.
Tests are made up of assertions. (schemepunk test)
provides these assertion
functions:
(assert-true <message> <value>)
(message
is optional)
(assert-false <message> <value>)
(message
is optional)
(assert-eq <actual> <expected>)
(assert-eqv <actual> <expected>)
(assert-equal <actual> <expected>)
(assert-approximate <actual> <expected> <error>)
(fail <message>)
(end-test-runner)
prints a report of passed/failed tests and ends the process
with the approporate return code, but you shouldn't need to call this on your
own. The test runner scripts in scripts
take care of finding all .test.scm
files in the project, running all of them, and running (end-test-runner)
at
the end.
The Makefile
contains usage examples for the test runner scripts. Finding the
test files and running the tests are split into two separate scripts, because
some of my projects need to search only specific subdirectories for test files.
(schemepunk vector)
Polyfilled alias for SRFI 133 (Vector Library). Exports one additional procedure:
(vector-filter <pred?> <vec>)
is the vector equivalent of filter
. It
returns a new vector containing all elements of <vec>
for which pred?
returns a non-#f
value.SRFI | Module | Description |
---|---|---|
1 | (schemepunk list) |
List library |
2 | (schemepunk syntax) |
and-let* |
8 | (schemepunk syntax) |
receive |
26 | (schemepunk syntax) |
cut and cute |
28 | (schemepunk syntax) |
format |
41 | (schemepunk stream) |
Streams |
64 | (schemepunk test) |
Unit tests |
111 | (schemepunk box) |
Boxes |
113 | (schemepunk set) |
Sets and bags |
125 | (schemepunk hash-table) |
Hash tables |
128 | (schemepunk comparator) |
Comparators |
132 | (schemepunk sort) |
Sorting libraries (partial) |
133 | (schemepunk vector) |
Vector library |
145 | (schemepunk syntax) |
Assumptions |
146 | (schemepunk mapping) |
Mappings (w/o (srfi 146 hash) ) |
152 | (schemepunk string) |
String library (reduced) |
156 | (schemepunk syntax) |
is and isnt |
158 | (schemepunk generator) |
Generators and accumulators |
162 | (schemepunk comparator) |
Comparators sublibrary |
166 | (schemepunk show) |
Monadic formatting |
173 | (schemepunk hook) |
Hooks |
197 | (schemepunk syntax) |
chain and related macros |
214 | (schemepunk flexvector) |
Flexvectors |
These modules are aliases for several common SRFIs and R7RS Large libraries,
along with implementations of these libraries for Schemes that don't provide
them by default. The implementations are in the polyfills
directory; they are
copied from either the SRFI documents or Chibi Scheme.
Copyright © 2020-2021 Adam Nelson
Schemepunk is distributed under the Blue Oak Model License. It is a MIT/BSD-style license, but with some clarifying improvements around patents, attribution, and multiple contributors.
Schemepunk also includes MIT/BSD-licensed code from the following authors: