Idioms of Minimal Scheme

Outline


The idioms of a language are really only learned through practice and exposure to more experienced users of that language. But I can point out a few idiomatic differences between Scheme and other computer languages you may encounter.

Naming conventions

Most Scheme objects are given lower-case names. An exception (presumably inherited from C) is that user-defined constants are named in ALL UPPER CASE. Multi-word names are usually separated by hyphens, e.g. this-is-a-long-name.

Assignment statements

In programming languages like Pascal, C, C++, and Java, perhaps the single most common kind of statement is assignment, which changes the value of a previously-defined variable. It is possible to do this in Scheme, but one can write large, sophisticated programs without ever using an assignment statement at all; indeed, I don't mention assignment statements until the end of my first-semester programming class. The Scheme idiom is instead to use function composition and recursion.

Loops and iteration

Scheme has looping constructs, slightly more powerful than the C/C++/Java "for" loop (to wit, they allow the simultaneous updating of several locally-bound loop variables), but they're not commonly used, because Scheme provides more elegant ways to handle most of the same problems.

Probably the most common application of loops in C/C++/Java is to do something to every element of an array or other data structure. Scheme programmers generally accomplish the same task either with recursion or with "mapping functions".

Numbers

New Scheme programmers with experience in other languages often overuse numbers, particularly as loop counters. For example, the Java code

    double sum=0.0;
    for (int i=0; i < myArray.length; i++) {
        sum += myArray[i];
    }
could be translated into a loop with array references in Scheme, looking something like this:
    (do ((i 0 (+ i 1)) (sum 0.0))
        ((>= i (length my-list)) sum)
        (set! sum (+ sum (list-ref my-list i))))
but a more natural and idiomatic solution is recursion:
    (define (add-up my-list)
        (cond [(empty? my-list) 0.0]
              [else (+ (first my-list)
                       (add-up (rest my-list)))]))
or, even simpler,
    (apply + my-list)

Numbers in other languages (and their close relatives, enumerated types) are also used to represent data which are fundamentally non-numeric. The natural way to do this in Scheme is usually through symbols.

My rule of thumb is that if numbers aren't part of the problem, they shouldn't be part of the solution.

Floating-point numbers

Programmers accustomed to other languages may also use floating-point numbers more than native Scheme programmers. If the number you're working with is an exact rational number, like 1/2 or 1/3, it can be represented exactly as a Scheme fraction; a floating-point number can only approximate it.
C/C++/Java/Pascal/BASIC programmers also sometimes use floating-point numbers for "REALLY BIG integers"; this isn't necessary in Scheme, because Scheme integers are limited only by the amount of memory in the computer, so if you want to find the 46th digit of the factorial of 120, go to it (by the way, it's 3).

Again, a rule of thumb: if the problem requires arithmetic operations other than addition, subtraction, multiplication, and division, or if it needs constants like pi or e, you'll need floating-point numbers; if not, you probably won't.


Last modified: Tue Jun 13 12:35:55 EDT 2000
Stephen Bloch / sbloch@adelphi.edu