The loop reads one line from the first file and one group of lines with a common key from the second file. The four conditions handle end-of-file, mis-matched keys in both directions, and matching keys. Get-group gets the next set of lines (which may be a singleton set) with a common key and returns them in a list, or the null list at end-of-file:

Get-group can’t know that a line is not part of the current set until it reads the line, by which time it is too late; this is a common problem for parsers, which need to lookahead in the input to know what to do. The problem is solved by an unget function that “un-reads” an input line. Getone checks if there is an ungotten line already saved before it reads a new line, implementing a classic pushback mechanism:

Here are prefix and suffix, which extract the key and the remainder of the fields from an input line. They are localized here to make them easy to change, for instance if you want to join tables on the n‘th field:

(define (prefix line) (car (string-split #\tab line)))

(define (suffix line) (cdr (string-split #\tab line)))

Here’s the example from the previous page. The 0 at the end of the two system calls is the value that cat returns to the shell: