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:
ioctl is only
required on Unix-based OSes.)
Schemepunk can also be built as a Chicken egg. Just run
-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
Polyfilled alias for SRFI 111 (Boxes). Exports one additional procedure:
(update-box! <box> <proc>)is equivalent to
(set-box! <box> (<proc> (unbox <box>))).
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
(btree <comparator> <max-size>)
(btree-ref <key> <value> <failure-proc>)(
(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-subset? <value-comparator> <btree1> <btree2>)
(btree=? <value-comparator> <btree1> <btree2>)
(btree<? <value-comparator> <btree1> <btree2>)
(btree-hash <value-comparator> <btree>)
¹ B-trees are faster than most Schemes' SRFI 146, but Gauche's
usually even faster.
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
documentation can be written like this for
'((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:
-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
--options passed to the app
args, a list of all non-option and non-command arguments passed to the app, as strings
command, the command name passed to the app, or
#fif there is no command
command-options, an alist of all options that occurred after the command name
command-args, a list of all non-option arguments that occurred after the command name, as strings
If parsing fails, a usage message is printed to
(current-error-port), and then Scheme is terminated with
(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
<proc>. If parsing fails, it will raise an error object for which
(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-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-usage, but also include
copyrightif they are present in the specification.
(command-error? <datum>)is a type predicate for the error objects raised by
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 text
doc- documentation paragraph, displayed at the start of the app's help text
doc-args- symbols or strings that describe the app's arguments in usage text; e.g.,
copyright- copyright message displayed at bottom of help text
options- alist of options for the app; each option's key is also its default long option name
commands- alist of commands for the app; each command's key is also its name
#t, app exits with an error if no command is provided
#t, an option is added with long name
--helpand short name
-hthat, if present, causes
run-applicationto print the app's help text and exit
#t, a command named
helpis added that, if selected and passed a command name as its only argument, causes
run-applicationto display that command's help text and exit
type- data type of the option's value, defaults to
boolean; options are
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 text
doc-value- name of the option's value, displayed in usage text, defaults to value of
short-doc- documentation shown in the app's usage text
doc- longer documentation shown in the command's usage text
doc-args- symbols or strings that describe the command's arguments in usage text; e.g.,
options- alist of options for the command; each option's key is also its default long option name
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-comparatoris a default comparator for symbols.
number-comparatoris a default comparator for numbers that is more general than SRFI 162's
fixnum-comparatoris 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
WIP simple Datalog logic programming library. Still unfinished, not much to see here. So far, it supports semi-naive evaluation and stratified negation.
Polyfilled alias for SRFI 214 (Flexvectors). No additional exports.
Combinators commonly used in functional languages like Haskell or ML.
(const <x>)returns a procedure that takes one argument, ignores it, and returns
(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).
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
Polyfilled alias for SRFI 125 (Intermediate Hash Tables). No
additional exports. Uses comparators from
Polyfilled alias for SRFI 173 (Hooks). No additional exports.
Minimal JSON parser. Can encode and decode JSON to/from a simple Scheme representation:
|JSON value||Scheme representation|
(read-json <port>)reads one JSON value from a port and returns it.
(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
json->stringconvert 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
eventis the event type and
payloadis an optional value. It takes a context object, which keeps track of nesting and object keys.
||Key name (string)|
||Error message (string)|
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
elemto the end of
(map-with-index <fn> <list>)is like
map, but it expects
fnto 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-gen <fn>)is a generator-style unfold.
fnis a lambda that takes two arguments, usually named
xto the end of the list being constructed, then recursively calls
doneis 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
listtwo elements at a time. It calls
fnwith three arguments. It raises an error if
listdoes not contain an even number of elements.
(fold-right-by-pairs <fn> <seed> <list>)is
(topological-sort <dependencies>)sorts a list of dependencies in dependency order.
dependenciesis 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.
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.
Mappings from one key to a set of values, based on
(schemepunk mapping) and
(schemepunk set). Uses comparators from
(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
(multimap? <datum>)is the type predicate for multimaps.
(multimap-value-comparator <mmap>)return the comparators used by
(multimap-ref <mmap> <key>)returns the set of values for
(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
<mmap>contains the value
<value>in any key's value set, and
(multimap-contains-key? <mmap> <key>)returns
<mmap>contains the key
(multimap-keys <mmap>)returns a list of the keys in
(multimap-values <mmap>)returns a list of all values in all value sets in
(multimap-value-sets <mmap>)returns a list of the value sets in
(multimap-key-count <mmap>)returns the number of keys in
(multimap-value-count <mmap>)returns the total number of values in all value sets in
(multimap-adjoin <mmap> <key> <value>)and
(multimap-adjoin! <mmap> <key> <value>)return a new multimap with
<value>added to the set of values for
<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
<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
<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
<mmap>in-place before returning it.
<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
<rhs>. If both multimaps contain the same key, the returned multimap will contain the union of both maps' value sets for that key.
<lhs>in-place before returning it.
(multimap-difference <lhs> <rhs>)returns a multimap that is the result of removing all key/value pairs in
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>to an equivalent, normalized form by removing any unnecessary
..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
(path-directory <path>)returns the path of the parent directory of
(path-strip-directory <path>)returns the final path element of
(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
Generates random numbers.
(random-integer <max>)generates a random exact integer between
(random-real)generates a random real number between
Polyfilled alias for SRFI 113 (Sets and Bags). No additional exports.
Uses comparators from
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 (
Schemepunk's SRFI 166 includes several additional operators and submodules. The additional exports, grouped by submodule, are as follows:
(call-with-output-generator <fmt> <proc>)is like
call-with-output, but passes a generator to
<proc>instead of a string.
Includes ANSI light colors:
as-gray (alias for
(boxed <fmts>…)returns a formatter that draws a box around
<fmts>using box drawing characters.
boxed/asciiare 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
<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
as-red, the box outline will be red. If the box should not be colored,
<v>are the horizontal and vertical line characters used to draw the box.
<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
pretty-json-colorare equivalents to
(schemepunk json)-compatible JSON data structures. They print JSON.
indent-sizeis a state variable for the number of spaces in a single pretty-printing indentation level. Defaults to
A simple interface to
(schemepunk show pretty) for print-statement debugging.
pretty-color, then prints a newline.
pretty-json-color, then prints a newline.
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
report-lineis 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
wrappedthat 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
<end-col>are the 0-based column range of the annotation.
<color>is a color formatter procedure, like
as-red, and should be
eachif the annotation is not colored.
<message>is the annotation message itself, and can be a string or
#f, the annotation will be an underline with no message.
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
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 <span>)returns the text content of
<span>as a string.
(span-color <span>)returns the color of
(schemepunk term-color)ANSI color, or
(text-span <str> <color>)constructs a
textspan from a string.
<color>is optional and defaults to
(whitespace-span <str>)constructs a
whitespacespan from a string.
<str>is optional and defaults to
(newline-span <str>)constructs a
newlinespan from a string.
<str>is optional and defaults to the string printed by
(span-map-text <proc> <span>)returns a copy of
<span>whose text content is the result of applying
(span-with-color <span> <color>)returns a copy of
<span>with the color
(char-generator->span-generator <gen> <word-separator?> <read-ansi-escapes?>)takes a generator of chars (
<gen>) and returns a generator of spans. Any
#\newlinecharacter becomes a
newlinespan, any group of characters for which
word-separator?returns true becomes a
whitespacespan, and all groups of characters between these become
<word-separator?>is an optional predicate and defaults to
<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
<port>, wrapped in ANSI escapes if the span has a color.
<port>is optional and defaults to
Polyfilled alias for SRFI 132 (Sort Libraries). No additional exports.
Alias for SRFI 41 (Streams). Because all supported Schemes include this SRFI, there is no polyfill. No additional exports.
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-ci<? family of comparison
(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.
λ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
λis not substitutable for
lambdain all situations.
(lambda x …)takes any numer of arguments, but
(λ x …)takes one.
(chain x (foo y _) (bar _ z)) ; => (bar (foo y x) z)
chain-lambdadefines a lambda using a
(chain-lambda (foo y _) (bar _ z))=
(lambda (x) (chain x (foo y _) (bar _ z))).
λ=>is shorthand for
(let1 <name> <value> <body>…)is shorthand for
letwith a single variable.
(if-let <name> <value> <then> <else>)is a version of
ifthat assigns the predicate
<value>to a variable
(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
matchpackages in Chibi and Gauche.
It supports only the basic features of
(chibi match). It is missing the
set!operators, and it does not support the symbol
...as an ellipsis operator (use
(match-let ((<pattern> <value>)…) <body>…)uses the pattern-matching syntax from
matchas destructuring assignment.
match-letrecare 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
guardform with pattern-matching. It matches the raised error against each
(define+ (<name> <params>… :optional <optional-params>… :rest <rest-param>) <body>…)is a form of
definethat supports destructuring assignment (as in
λ) and optional parameters. It uses Gauche's syntax for optional and rest parameters. The
:restsections are optional. Each
<optional-param>may be a symbol or a list
(<name> <default>). The
<rest-param>sections may be
ANSI escape codes for terminal colors.
(write-in-color <color> <string>) writes
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
<color> is a color object, which may be one of:
- The 16 colors
- The 8 bold colors
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:
- Foreground colors
- Background colors
Order does not matter, and any or all of these can be omitted.
with no arguments is the color reset escape code, also available as
If your terminal supports 256 colors or true 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
For more fine-grained control,
(write-color <color>) writes a single ANSI
escape code. Make sure to reset with
(reset-color) after writing!
Test suites are defined as
(test-group <name> <tests>…), where
one or more
(test <name> <expressions>…) clauses. Test suite files have the
Tests are made up of assertions.
(schemepunk test) provides these assertion
(assert-true <message> <value>)(
(assert-false <message> <value>)(
(assert-eq <actual> <expected>)
(assert-eqv <actual> <expected>)
(assert-equal <actual> <expected>)
(assert-approximate <actual> <expected> <error>)
(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
files in the project, running all of them, and running
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.
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
pred?returns a non-
||Sets and bags|
||Sorting libraries (partial)|
||String library (reduced)|
||Generators and accumulators|
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 also includes MIT/BSD-licensed code from the following authors:
- SRFI 113, 125, 132, and 133 implementations, and parts of SRFI 166 implementation, are taken from Chibi Scheme, copyright © 2009-2020 Alex Shinn
- SRFI 128 implementation copyright © 2015 John Cowan
- SRFI 146 tests and original reference implementation copyright © 2016-2017 Marc Nieper-Wißkirchen
- SRFI 152 tests and original reference implementation copyright © 2017 John Cowan
- SRFI 156 implementation adapted from reference implementation, copyright © 2017 Panicz Maciej Godek
- SRFI 158 implementation copyright © 2015 Shiro Kawai, John Cowan, Thomas Gilray