matrico’s Utilities Module
This is the base module of the
matrico project and imported by every other module.
It contains a collection of miscellaneous bindings, macros and functions for general use.
You can take a look at the
src/utils.scm source file here.
Scheme’s macro system is insanely powerful.
However, I often only need a handful of macro helpers.
First, the generic
define-syntax is to bulky if you only have a single rule;
for this, I use a macro that makes the syntax definition look like a function definition, inspired by Guile.
Second, I need to rename bindings on-the-fly, for which I use a simple macro also PC Scheme had.
Also, I require a shortcut for asserting a variable argument list of tests, typically to check argument types and properties.
There are two reason for not using a function here: asserts are removed by the CHICKEN compiler in “unsafe”-mode, so this might litter,
and, I am using
and which I cannot pass into
apply since it is special.
Lastly, I was intruiged by Clojure’s rich comments, which were already part of the T language.
(define-syntax-rule )- Wrapper for single rule macros.
(alias aka name)- Replaces first argument with second argument.
(must-be arg ...)- Wrapper for
andwith variable number arguments.
(comment ...)- S-expression comment, all content is ignored and void is returned.
comment macro will not be found in the release code bases, I just use it during development.
I never warmed up to Lisps’
cdr function names, even given the
sometimes useful predefined compositions of
cdr for more info).
I prefer StandardML’s “head” (
hd) and “tail” (
tl), and even if
not all cdrs are tails, every coin has a pair
of heads and tails.
Then, Lisp has
nil as a name for the empty list,
and I prefer three letters to three symbols typing-wise.
I note here, that in Lisp the empty list also is a boolean false value, while in Scheme only and only
is false. Finally, I find Racket’s
empty? is much more readable then
null?. Thus the following names are bound:
nil- Name for the empty list symbol
(head lst)- Alternate name for
carreturning first member of argument pair.
(tail lst)- Alternate name for
cdrreturning second member of argument pair.
(empty? lst)- Alternate name for
null?returning true if tail of argument pair is nil.
These are bindings and can’t use the
alias macro, otherwise they couldn’t be passed as functions.
For performance and readability reasons I want to ensure and document that for indexing operations fixed-size integers and integer operations are used. CHICKEN has the matching (chicken fixnum) module for this purpose. However, I needed to add a few functions, like increment and decrement as well as predicates comparing to zero:
(fx+1 x)- Increment fixnum argument.
(fx-1 x)- Decrement fixnum argument.
(fx=0? x)- Returns true if fixnum argument is zero, false otherwise.
(fx<0? x)- Returns true if fixnum argument is less than zero, false otherwise.
(fx>0? x)- Returns true if fixnum argument is greater than zero, false otherwise.
(fx<=0? x)- Returns true if fixnum argument is less or equal to zero, false otherwise.
(fx>=0? x)- Returns true if fixnum argument is greater or equal to zero, false otherwise.
As integers are so fundamental for programming and it is hard to imagine using the above
fixnum helpers without other fixnum functions, I let the
(chicken fixnum) module.
Rarely, one needs to extract a part of list between two indices, similar to
the non-standard but prevalent
subvector for vectors. However, there is a specific
use for this un-schemy (due to the indexing of a list) function.
Furthermore, heuristically it turned out using folding via (
foldr) instead of
append to append an element to a list is more memory efficient, thus a
fold-based append variant is supplied.
Unlike in SRFI-1, my
all? (“all” instead of “every”) functions return boolean values, and thus have
question marks signifying a predicate. These leads to:
(append* lst any)- Returns argument list appended with element argument.
(sublist lst start end)- Returns list partition of list argument inbetween the index arguments.
(any? pred lst)- Returns true if any element of list argument applied to function argument is true, false otherwise.
(all? pred lst)- Returns true if all elements of list argument applied to function argument are true, false otherwise.
A classic example for recursive computation is the factorial. Here, it is implemented to be able to test another function from another module. Furthermore, the related binomial cofficient is provided where the implemented algorithm, Pascal’s rule, hints at its use.
(factorial n)- Returns product of consecutive integers up to argument, starting at one.
(binomial n k)- Returns binomial coefficient for given integer arguments.
Note, that a computation of the binomial coefficient via its iterative definition (using the factorial) is very inefficient.
Scheme, particularly CHICKEN Scheme, is awesome. Whatever you can imagine, be it docstrings or a data-file loading, one can implement with a few lines of code:
(define* ...)- Defines a binding together with a docstring for various forms of
(load* pathstr)- Loads and evaluates file a argument string path and returns the result of the last expression.
define* is a language extension via a pattern matching macro,
load* is a function using