Reflections on using Scheme

NOTE HXA7241 2011-02-06T22:36Z

The Scheme (R5RS) translation of the MiniLight renderer has just been finished (the latest of 12 translations, 8 by the author). So now is a good time for some reflections on the language.

MiniLight

MiniLight is a sort-of toy, a reference, a didactic example, a basis for experiment, and a way to exercise one's programming language learning. Once you have completed a translation into an unfamiliar language, you will likely have learned that language well enough to be basically competent.

Scheme

The central impression of Scheme is one of distinct purity and regularity. It has a simple form, and shows it simply.

This is because functional languages have recursion, and hence hierarchical structure, at their heart, and predominantly so. That is the key to all software structure, and it is their focus point. (In contrast, imperative languages have linear jumps instead – Turing machines compared to Lambda calculus. And why is hierarchy the key to software structure? Because it is the key to all engineering structure – all determinate construction is founded on nested decomposition of structure.)

Scheme programs are also at the compact end of the scale, although line-counting does not do it justice since its normal layout produces short lines.

Consequently, it seems almost a good primal algorithm language, for reference versions – but really it would need to be more completely defined to do that properly.

There a number of minor weaknesses: list/vector index-addressing verbosity, lack of OO mechanism (and so verbosity of record-structure addressing), lack of module and namespace mechanism, lack of dictionary type. But all these can be added with the language itself, or provided in SRFIs or various particular implementations. However it should probably be considered a further weakness that these are not standardly supported.

One question against its otherwise felicitous disposition and expression of its elements is the separateness of macros. A macro, e.g. ‘and’ and ‘or’, looks like a lambda, yet cannot be passed like a lambda. Should there really be this mismatch, where something is seemingly integrated but actually not? How much could macros be replaced by specific control of argument passing? – as in Scala a parameter can be set to be call-by-name or call-by-value.

The great deficit is lack of type checking. Building incrementally with small pieces and working by REPL is not a substitute. Lisp needs proper typing.

Stepping back, perhaps the larger result of its basic form is that it softens the boundary between language and library. And this gives rise to a special problem or question: what kind of ways should there be to layer language and library design? What should be language, or core language, or library, or core library? How should those be evolved and standardised?