Yourfavoritenerd
Yourfavoritenerd

Reputation: 1

Error of calling function in Scheme

my code shows this error - function call: expected a function after the open parenthesis, but received (void)

I dont know why. its on the 3rd line

(define countdown
  (lambda (n)
    (cond ((zero? n) (( display "Time") (newline)))
       (else
        ((display n) (newline) (countdown ( - n 1)))))))

Upvotes: 0

Views: 722

Answers (2)

Sylwester
Sylwester

Reputation: 48735

Here is a definition of abs:

(define (abs n)
  ((if (< n 0) - +) n))

When given a negative number the result of evaluating - is returned else + so if you were to pass -5 it becomes (- -5) and in the case 5 is passed it becomes (+ 5). Both evaluate to 5. Do you see that I am using the return of an expression as a function? That is what the parentheses mean.. In a C-like language I might have done something like (n < 0 ? sub : add)(0, n)

In your cond when disregarding the parentheses that surround each term you have double parentheses several places:

((display "Time") (newline))
((display n) (newline) (countdown ( - n 1)))

Both of them assume the display function returns a function one can apply. It doesn't and it will fail with telling you that is not a function.

If you were looking to group commands together, like {} in C languages, then you are looking for the special form begin. eg. (begin 1 2 3) ; ==> 3

cond has explicit begin in each of its terms so if you just wanted to get each part evaluated the fix looks like this:

(define (countdown n)
  (cond ((zero? n) (display "Time") (newline))
        (else (display n) (newline) (countdown (- n 1)))))

An alternative way to format it is this:

(define (countdown n)
  (cond 
    ((zero? n) 
     (display "Time") (newline))
    (else 
     (display n) 
     (newline) 
     (countdown (- n 1)))))

Notice parentheses are aligned with the same level so you know when the next term starts. It helps you read the code since your formatting in the question gives no clue. Get a proper editor to do your coding in.

Upvotes: 1

assefamaru
assefamaru

Reputation: 2789

When using cond statements, you don't need parentheses around consequence expressions. The general structure is:

(cond (condition1 expr1 expr2 expr3 ...)       ;; NOT (... (expr1 expr2 expr3 ...))
      (condition2 expr1 expr2 expr3 ...)
      ...
      (else ...))

so your specific case can be fixed to:

(cond ((zero? n) (display "Time") (newline))
      (else (display n) (newline) (countdown (- n 1))))

and the procedure can be rewritten as:

(define countdown
  (lambda (n)
    (cond ((zero? n)
           (displayln "Time"))
          (else
           (displayln n)
           (countdown (- n 1))))))

If you include parentheses around the consequence expressions by, for example, having

((display "Time") (newline))

then this will be interpreted as a procedure

(procedure-name arg)

where procedure-name takes the value of (display "Time"), and arg takes the value of (newline). Since (display "Time") is only for side effect with no return value, you get the constant #<void> for procedure and hence the error message: expected a procedure that can be applied to arguments.

Upvotes: 1

Related Questions