0

I'm new to Scheme and to functional programming in general.

As part of an exercise, I try to implement a function that that takes a number n and prints line by line first n Fibonacci numbers

The problem is that when the program reaches the recursive call, it doesn't recognize n and so I get contract violation error.

From exploring the web I think I need to use let function in some way but I'm not sure how.

Here's the code:

(define fibo (lambda (n)
           (if (= n 1)
                 1
                 (if (= n 2)
                   (begin
                     (display "1")
                     (newline)
                     1)
                   (begin
                     (display
                      (+ (fibo (- n 1)) (fibo (- n 2))))
                     )))))

And the error I get is:

contract violation
expected: number?
  given: #<void>
  argument position: 1st
  other arguments...:

Thank you

Noam
  • 1,640
  • 4
  • 26
  • 55

2 Answers2

2

The reason of the error is the fact that fibo is supposed to be a function that returns an integer, while in the second case of the inner if you simply print a value (and display returns #<void>, which is not an integer).

This is immediately clear if you indent properly your code:

(define fibo
  (lambda (n)
    (if (= n 1)
        1
        (if (= n 2)
            (begin
              (display "1")
              (newline)
              1)
            (begin
              (display (+ (fibo (- n 1)) (fibo (- n 2)))))))))

You can note that the first branch of the second if terminates with 1, which is returned, while the second branch returns the result of the display.

If you remove the various display calls (which are not useful since the values printed contains many repetitions), the function produces the correct result:

(define fibo
  (lambda (n)
    (if (= n 1)
        1
        (if (= n 2)
            1
            (+ (fibo (- n 1)) (fibo (- n 2)))))))

Note that it can be rewritten in a more concise form:

(define fibo
  (lambda (n)
    (if (<= n 2)
        1
        (+ (fibo (- n 1)) (fibo (- n 2))))))

Finally, if you want to display all the numbers of Fibonacci until a certain value, you could define a function like:

(define display-all-fibo
  (lambda (n)
    (define display-fibo
      (lambda (i)
        (if (<= i n)
            (begin
              (display (fibo i))
              (newline)
              (display-fibo (+ i 1)))
            (display "Done!"))))
    (display-fibo 1)))

(display-all-fibo 9)

1
1
2
3
5
8
13
21
34
Done!
Renzo
  • 26,848
  • 5
  • 49
  • 61
2

Split the problem up. Separate dirty side effects from the function that generates the numbers:

(define (fib-list from to)
  ...)
(fib-list 10 20)
; ==> (55 89 144 233 377 610 987 1597 2584 4181 6765)

Then it's easy to make a function that prints said list:

(define (print-fib-list from to)
  (for-each displayln (fib-list from to)))

This uses for-each but it's pretty much just as easy doing it with recursion.

Sylwester
  • 47,942
  • 4
  • 47
  • 79