Scheduled Maintenance: We are aware of an issue with Google, AOL, and Yahoo services as email providers which are blocking new registrations. We are trying to fix the issue and we have several internal and external support tickets in process to resolve the issue. Please see: viewtopic.php?t=158230

 

 

 

very basic lisp question

Programming languages, Coding, Executables, Package Creation, and Scripting.
Post Reply
Message
Author
johnc0123456789
Posts: 27
Joined: 2013-09-25 01:10

very basic lisp question

#1 Post by johnc0123456789 »

Hi all. Apologies for asking a question that seems like it should be ridiculously trivial, but I've been googling and trying stuff for hours and can't figure out what the problem is. All I want to do is write a lisp function that prints each element of a list on a different line. Here's my code:

Code: Select all

(define print-list
  (lambda (l)
    (if (null? l)
	   (display "done\n")
        (  (display (car l))  (newline)  (print-list (cdr l)) ))))


(print-list '(1 2 3 4 5) )
And here's how I'm running it and the output I get:

Code: Select all

john@home:~/code/lisp$ tinyscheme helloworld.scm
1
2
3
4
5
done
Error: (helloworld.scm : 8) illegal function 
Errors encountered reading helloworld.scm
john@home:~/code/lisp$
So the code behaves exactly as I would expect, then I get the error message and exit. I don't understand what I've done wrong!

User avatar
Telemachus
Posts: 4574
Joined: 2006-12-25 15:53
Been thanked: 2 times

Re: very basic lisp question

#2 Post by Telemachus »

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)))))
"We have not been faced with the need to satisfy someone else's requirements, and for this freedom we are grateful."
Dennis Ritchie and Ken Thompson, The UNIX Time-Sharing System

Post Reply