These guidelines apply to Scheme and, by extension, to most programming languages. For tips related to PLT Scheme specifically, see PLT Scheme Tips.
A function should have one and only one well-defined task to do, such as calculating a value, making a decision, displaying output, etc. Functions like this are short, easy to read, easy to name, and easy to reuse.
For more on this point, see The Cardinal Rule of Functions.
This is probably the most important factor in readable code, after One function to a function. It is also the most difficult to summarize. At Roedy Green's tongue in cheek web site How to write unmaintainable code, naming is the single biggest entry, because there are so many ways to do it wrong. See also my EECS 325 essay on naming.
If a conditional is being used to return a value, then always have an else clause to make clear what the return value is if no other branch is selected. For example, consider an expression that was intended to return the minimum of three values:
(cond ((and (<= x y) (<= y z)) x) ((and (<= y x) (<= y z)) y) ((and (<= z y) (<= z x)) z))
Can you tell at a glance if this conditional is guaranteed to return 1, 2 or 3? Or might all three branches fail and false will be returned? If in fact it does always return 1, 2, or 3, that means that the last test is redundant. If the conjunctions in the first two branches are false, the final one can never be false, so there's no point in executing it. Hence, the clearest and most efficient way to write this is:
(cond ((and (<= x y) (<= y z)) x) ((and (<= y x) (<= y z)) y) (else z))
In fact, using an else means we can use the simpler non-compound less-than operator. That wasn't possible without the else. So our final code is:
(cond ((and (< x y) (< y z)) x) ((and (< y x) (< y z)) y) (else z))
Unless specifically instructed not to in an exercise, look for and use standard library functions where appropriate. Even when the function is trivial, e.g., sqr or abs, it's important to use the standard functions.
Comments should be your last resort for making code clear. Comments are
The worst comments are redundant ones:
;;; increment the year (set! year (+ year 1))
If code is not self-explanatory, change the code. Use better names to explain what variables contain. Create well-named subfunctions to explain what subtasks are being carried out.
Save comments for information good names and code structure can't convey, e.g.,
The other legitimate use of comments is for document generation, e.g., javadoc. Note that these comments are written for users of the code, not maintainers, and they are kept outside the actual function bodies, to minimize clutter.