The Explorer

The Adventures of a Pythonista in Schemeland/17

by Michele Simionato

March 3, 2009



The R6RS standard provides a few list utilities; the SRFI-1 provides a few others. Nevertheless the offering is incomplete: in particular a list comprehension syntax is missing. Therefore I have decided to distribute a library providing list comprehension and more. Such library will be useful for future episodes of my Adventures, in particular for part IV, about advanced macro programming. After all, macro programming is nothing else than manipulation of code seen as a nested list of expressions.

With a remarkable lack of fantasy, I have decided to call the library list-utils and to put it in a package called aps ( aps of course stands for Adventures of a Pythonista in Schemeland and not for American Physical Society ;). In this way I will be contributing to the entropy and I will be littering the world with yet another version of utilities that I would rather not write, but this cannot be helped :-(

For your convenience, I have added in the library the Python-style utilities range , zip , transpose , enumerate I did discuss in episodes 7 and 8, as well as the let+ list destructuring macro I introduced in episode 15. I have also added the reference implementation of SRFI-26 i.e. the cut and cute macros described in episode _14. Moreover, the aps package contains the testing framework discussed in episode 11, renamed as (aps easy-test) and slightly improved (the improvement consists in the addition of catch-error macro, which captures the error message). Finally, the aps library includes a more recent version of sweet-macros than the one I discussed in episode 9, so you should replace the old one if you have it.

You can download the package from here: http://www.phyast.pitt.edu/~micheles/scheme/aps.zip

Just unzip the archive and put the files somewhere in your path:

$ cd <DIRECTORY-IN-YOUR-SCHEME-PATH> $ unzip aps.zip inflating: sweet-macros.sls inflating: aps/cut.sls inflating: aps/easy-test.sls inflating: aps/list-utils.sls ...

You can test the library as follows:

$ ikarus --r6rs-script aps/test-all.ss ......................... Run 25 tests. 25 passed, 0 failed

Currently all the tests pass with the latest development version of Ikarus. They also pass with the latest development version of Ypsilon and with PLT Scheme version 4, except for the test zip-with-error :

(test "zip-with-error" (catch-error (zip '(a b c) '(1 2))) "length mismatch")

However, this is an expected failure, since the error messages are different between Ikarus, Ypsilon and PLT Scheme. Clearly, checking for an implementation-dependent error message is a bad idea and I could have thought of a better test, but I am lazy; moreover, I do not want to discuss the error management mechanism in Scheme right now, since it is quite advanced and it is best deferred to future episodes.

Larceny Scheme is not supported since it does not support the .IMPL.sls convention. When it does, it could be supported as well, expecially if I get some help from my readers.

If you are wondering about the so-called .IMPL.sls convention, let me explain that it is a non-standard convention to enable portability about different R6RS implementations. In particular the aps library contains three modules compat.ikarus.sls , compat.mzscheme.sls and compat.ypsilon.sls following the convention. When I write (import (aps compat)) in Ikarus, the file compat.ikarus.sls is read; when I import (aps compat) in PLT, the file compat.mzscheme.sls is read; and finally for Ypsilon the file compat.ypsilon.sls is read. This mechanism allows for writing compatibility wrappers; for instance, here is the content of compat.mzscheme.sls :

#!r6rs (library (aps compat) (export printf format gensym pretty-print) (import (rnrs) (only (scheme) printf format gensym pretty-print)))

Basically all decent Scheme implementations provide printf , format , gensym and pretty-print functionality, usually with these names too, but since they are not standard (which is absurd IMO) one is forced to recur to do-nothing compatibility libraries, which just import the functionality from the implementation-specific module and re-export it :-(

You can try the (aps list-utils) library as follows:

> (import (aps list-utils)) > (enumerate '(a b c)) ((0 a) (1 b) (2 c))