I'm pretty sure that the
original poster asked this somewhere else and received an answer there. However, I'll write an answer here for people on this forum too.
A Scheme
if expression has three parts: (1) a
test-expression, (2) a
then-expression, and (3) an
else-expression. The test-expression is evaluated first. If it evaluates to a true value, the then-expression is evaluated and the else-expression is ignored. If the test-expression evaluates to a false value, the else-expression is evaluated and the then-expression is ignored.
The problem here is the else-expression, copied below. (I've laid it out differently to make clear that it has three parts. This will matter later.)
Code: Select all
(
(display (car l))
(newline)
(print-list (cdr l))
)
That entire thing is
a single expression, but it's illegal in Scheme, as written. Scheme interprets
( a b c ) as a
procedure (i.e., function) call:
( operator operand operand ). (E.g.,
(+ 2 3). The
+ is the operator, standing for the addition function, and
2 and
3 are the arguments to the addition function. When you "apply" addition to 2 and 3, you get 5.) Scheme's interpreter always tries to evaluate the first item and then apply it as a function to the next two items, each of which is taken as an argument to the function that is the first item. The first item in this else-expression is
(display (car l)), but this is not a function that can be applied to
(newline) and
(print-list (cdr l)). That's where the error comes from.
The mistake is probably a result of the OP being used to procedural languages (like, say, C) which give the
else part of an
if...else and implicit block structure, telling the interpreter to run each statement sequentially. To get that effect here, you can simply add
begin which tells the Scheme interpreter to treat what follows as a block, running each expression in sequence, returning the value of the last expression and ignoring all the other return values. (A few people suggested this on the Stack Overflow question that I linked above.) That would look like this:
Code: Select all
(define print-list
(lambda (l)
(if (null? l)
(display "done\n")
(begin
(display (car l))
(newline)
(print-list (cdr l))))))
An alternative,
suggested by someone on Stack Overflow is to change from an
if expression to a
cond...else expression. With a
cond...else expression, you can put a sequence of statements in the
else.
Code: Select all
(define (print-list a-list)
(cond ((null? a-list) 'done)
(else
(display (car a-list))
(newline)
(print-list (cdr a-list)))))