Robert Fisher

Just thinking out loud

Scheme idioms

If you register and log in you can add comments to my pages. If viewing the main blog page, click the # underneath an entry to comment on it.

Use #f as a sentinel value. (See also: anaphoric if)

(cond ((return-an-object-or-false)
       => (lambda (the-object)
            (do-something-with-object the-object))))

(let ((the-object (or (return-an-object-or-false)
                      default-object))))

It'd be nice if read-line followed this convention.

(define (anaphoric-read-line port)
  (let ((line (read-line port)))
    (if (eof? line) #f line)))

Here's a macro for anaphoric cond:

(My attempt at supporting "non-binding" clauses is flawed. I may have to reintroduce some sort of literal symbol to indicate when you want binding. e.g. (line <- (anaphoric-read-line) (display line)))

(define-syntax if*
  (syntax-rules ()
    ((_ "aux" ((var test) form . forms))
     (test => (lambda (var) form . forms)))
    ((_ "aux" (test form . forms))
     (test form . forms))
    ((_ clause ...)
     (cond (if* "aux" clause) ...))))

It might be used like this:

(if* ((the-object (return-an-object-or-false))
      (do-something-with-object the-object))
     ((line (anaphoric-read-line))
      (display line)
      (newline))
     (#t
      (display "The else case.")
      (newline)))

I like predicates that return their argument instead of #t. Useful for anaphoric conds.

(define (make-predicate-better p?)
  (lambda (obj)
    (if (p? obj)
      obj
      #f)))
(define symbol?? (make-predicate-better symbol?))

For conditionals, just use cond. Unless it's the simple kind of thing you would use ?: for in C; if is OK for that. In almost all cases, cond doesn't have significantly more overhead than if, when, or unless.

Implicit begin macros

Macros often contain a form . forms in the pattern that expands into a (begin form . forms) or (lambda () form . forms) or something similar.

(define-syntax when
  (syntax-rules ()
    ((when condition form . forms)
     (if condition (begin form . forms) #f))))

See JRM's Syntax-rules Primer for the Merely Eccentric

The identity function is spelled values. The values function is equivalent to (lambda (x) x).