2017-03-31 22 views
0

我是Scheme和函数式编程的新手。在内部函数中使用输入参数的方案

作为工作的一部分,我试图实现一个功能,这需要通过线第一n Fibonacci数一数n并打印线

的问题是,程序到达递归调用的时候,这不是”不承认n,所以我得到违反合同的错误。

从探索网络我想我需要使用let功能,但我不知道如何。

下面的代码:

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

而我得到的错误是:

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

谢谢

回答

2

错误的原因是fibo应该是一个事实函数返回一个整数,而在内部if的第二种情况下,您只需输出一个值(并且display返回#<void>,它不是一个整数)。

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

你可以注意到,第二if的第一分支1,这是返回终止,而第二分支返回的结果:

如果缩进正确的代码是立即清除display

如果除去各种display电话(这是没有用的,因为印刷的值包含了许多重复),该函数将产生正确的结果:

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

注意,它可以在一个更简洁的形式被改写:

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

最后,如果你想显示斐波那契的所有数字,直到一定值时,你可以定义像函数:

(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! 
+0

谢谢你的详细回答,但我不允许使用'when'语句...有没有其他的方式呢? – Noam

+0

我改变了答案。 – Renzo

2

解决问题。从生成号码功能独立肮脏的副作用:

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

然后,它很容易使一个功能,打印表示名单:

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

它使用for-each但它是非常简单,只是简单做与递归。