2017-01-05 1 views
1

Ich habe ein Projekt in Schema, in dem ich eine unendliche Folge von Zahlen implementieren muss. Ich kann keine in einem Schema integrierten komplexen Funktionen verwenden, und ich weiß einfach nicht, wie ich meine Sequenz unendlich machen kann, ohne dass das Programm in der Endlosschleife abstürzt. Ich muss es nicht wirklich ausgeben, aber ich muss es benutzen können.unendliches Sequenzschema zur unendlichen Sequenz

(seq n) ;;output: n,n+1,n+2,n+3.... to infinity (seq 5) ->5,6,7,8,9... 

Im Moment habe ich eine Sequenz bis n + 7, aber ich brauche diese bis ins Unendliche:

(define (seq n) 
    (define (asc-order LIST counter) 
    (cond ((= counter (+ n 7)) LIST) 
      (else (asc-order (append LIST (cons (+ counter 1) '())) 
      (+ counter 1))))) 
(asc-order '() (- n 1)) 
) 

IO Beispiel (Es funktioniert, aber ich brauche es unendliche Folge):

>(define s (seq 3)) 
>(car s) 
3 

Antwort

3

Sie können eine unendliche Sequenz als eine Funktion darstellen, die jeweils ein Element erzeugt. Der Benutzer (Consumer) kann dann die Funktion aufrufen, wobei jeweils ein neues Element der Sequenz benötigt wird.

Ein Beispiel:

(define (f x) (* x x)) 

(define seq 
    (let() 
    (define n 0)  ; current index 
    (lambda()   ; the function that is to be called repeatedly 
     (define a (f n)) ; compute the new element 
     (set! n (+ n 1)) ; compute new index 
     a)))    ; return the new element 

(seq) ; compute element 0 
(seq) ; compute element 1 
(seq) ; ... 
(seq) 
(seq) 
(seq) 

Dies zu auswertet:

0 
1 
4 
9 
16 
25 

zu schreiben, um (sequence->list s n) die die ersten n Elemente der Folge s, bilden eine Schleife berechnet die s insgesamt n ruft mal - und sammle die Ergebnisse in einer Liste.

+0

Dank @soegaard, aber wie ich bereits erwähnt habe zu verwenden, nicht erlaubt Einbau in nicht-primitiven Funktionen, particaularly gesetzt! – mooly

0

Hier ist eine andere Lösung verzögerte Auswertung mit:

(use-modules (ice-9 receive)) 


(define (seq f) 
    (let loop ((n 0)) 
    (lambda() 
     (values (f n) (loop (1+ n)))))) 


(define squares (seq (lambda (x) (* x x)))) 

(receive (square next) (squares) 
    (pk square) ;; => 0 
    (receive (square next) (next) 
    (pk square) ;; => 1 
    (receive (square next) (next) 
     (pk square) ;; => 4 
     (receive (square next) (next) 
     (pk square))))) ;; => 9 
+0

Dies funktioniert unter Guile 2.x – amirouche

1

Der Schlüssel ist, Auswertung der Liste zu verzögern, indem ein Verfahren um ihn herum gewickelt wird.

Hier ist die einfachste Implementierung, die ich mir vorstellen kann.
Es ist nur "faul" im Schwanz.

(define (seq n) 
    (cons n (lambda() (seq (+ n 1))))) 

(define (seq-car s) 
    (car s)) 

(define (seq-cdr s) 
    ((cdr s))) 

Beispiel für die Verwendung:

; Get the 'n' first elements of 's'. 
(define (seq-take n s) 
    (if (<= n 0) 
     '() 
     (cons (seq-car s) (seq-take (- n 1) (seq-cdr s))))) 


> (define s (seq 10)) 
> s 
'(10 . #<procedure>) 
> (seq-take 5 s) 
'(10 11 12 13 14) 
+0

ein häufiger Fehler bei der 'Take'-Implementierung ist die Überproduktion um 1. Für n = 1 ist es nicht nötig, den Tail zu erzwingen, der auch divergieren könnte. :) –

Verwandte Themen