views:

352

answers:

2

I'm in the process of learning Scheme. I recently spent (too much!) time trying to find a bug in a program before I realized I was missing the 'else' word in a cond clause. But the behavior in such circumstances appears to be a little weird. Experimenting with the conditions with just a simple program (below) the 'whatever' gets displayed as expected in the else clause, but also gets displayed, but without the 'else', gets displayed with the surrounding double quotes and the un-interpreted new line printed literally. Can anybody explain to me what's happening? TIA.

   (define (foo x)
    (cond ((eq? x 0) (display "zero\n"))
          (display "whatever\n")))

   (define (bar x)
    (cond ((eq? x 0 ) (display "zero\n"))
          (else (display "whatever\n"))))

In the repl window:
Welcome to DrScheme, version 4.1.5 [3m].
Language: Pretty Big; memory limit: 128 megabytes.
> (foo 0)
zero
> (bar 0)
zero
> (foo 2)
"whatever\n"
> (bar 2)
whatever
>
+4  A: 

In the foo function, the cond statement evaluates display as the condition to test. Since there is indeed a symbol called display, it evaluates to true, so the "whatever\n" is then evaluated as the result of (foo 2).

Greg Hewgill
Your answer was wonderfully clear and equally deserving of accepted answer. I gave it to Charlie for all his typing. Thanks so much.
Leonard
No worries, he deserves it!
Greg Hewgill
Well, I upvoted you anyway, Greg.
Charlie Martin
+9  A: 

"else" is just a synonym for "true". The way to read cond is as a series of tests, where the first test that's true causes that form to be evaluated.

(cond  ( (test) (do this) )
       ( (test) (do this) ) )

Here's your first one

 (cond ((eq? x 0) (display "zero\n"))
        (display "whatever\n")))

cond looks at (eq? x 0) and determined that's false. The next clause is (display "whatever\n"). It looks at display, and since display is not nil, it's true. It then evaluates the string "whatever\n", which simply evaluates to itself. So the value of the cond is then "whatever\n".

Now, here's you second one:

(cond ((eq? x 0 ) (display "zero\n"))
       (else (display "whatever\n"))))

Here, the first test is false, and it goes on to the second one, which is else and which evaluates to true. (If you think about it, that's what the "else" means in a normal if-then-else: "true for all the cases where none of the previous tests were true.")

Now, the form following it is (display "whatever\n"). That's a function that sends the string argument to the console and returns nothing because that's what display happens to do. In another scheme, it might return its string value as well as printing it, in which case you'd see

whatever
"whatever\n"
Charlie Martin