2017-03-31 1 views
0

Ich bin neu in Scheme und auf die funktionale Programmierung im Allgemeinen.Schema mit Eingangsparameter in innere Funktion

Im Rahmen einer Übung, ich versuche, eine Funktion zu implementieren, dass das dauert eine Reihe n und druckt Zeile für Zeile erster n Fibonacci-Zahlen

Das Problem ist, dass, wenn das Programm den rekursiven Aufruf erreicht, es doesn‘ t erkennen n und so bekomme ich einen Vertragsverletzungsfehler.

Von der Erforschung des Netzes glaube ich, ich muss let Funktion in irgendeiner Weise verwenden, aber ich bin mir nicht sicher, wie.

Hier ist der 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)))) 
        ))))) 

Und die Fehler, die ich bekommen ist:

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

Danke

Antwort

2

Der Grund des Fehlers ist die Tatsache, dass fibo soll eine sein Funktion, die eine ganze Zahl zurückgibt, während im zweiten Fall der inneren if Sie einfach einen Wert (und display gibt #<void>, die keine ganze Zahl ist).

Dies wird sofort klar, wenn Sie richtig Code einrücken:

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

Sie können beachten Sie, dass der erste Teil des zweiten if mit 1 beendet, die zurückgegeben wird, während der zweite Zweig das Ergebnis der Retouren display.

Wenn Sie die verschiedenen display Anrufe entfernen (die nicht geeignet sind, da die gedruckte Werte viele Wiederholungen enthalten) erzeugt die Funktion das korrekte Ergebnis:

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

Beachten Sie, dass es in einer prägnanten Form neu geschrieben werden kann :

:

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

Schließlich, wenn Sie alle Zahlen der Fibonacci bis zu einem bestimmten Wert anzuzeigen möchten, können Sie eine Funktion wie definieren

(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

Vielen Dank für Ihre ausführliche Antwort, aber ich darf nicht 'when' Aussage verwenden ... Gibt es eine andere Möglichkeit, es zu tun? – Noam

+0

Ich habe die Antwort geändert. – Renzo

2

Teilen Sie das Problem auf. Separate schmutzige Nebenwirkungen aus der Funktion, die die Zahlen erzeugt:

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

dann eine Funktion zu machen, ist es einfach, die Drucke der Liste:

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

Dies verwendet for-each aber es ist ziemlich einfach, wie einfach es zu tun mit Rekursion.

Verwandte Themen