2017-05-08 1 views
1

DrRacket Benutzer.While-Schleifen Arbeitsmechanismus eines Programms in Schema

ich kämpfen, um zu verstehen, wie dieses Programm works.I es selbst geschrieben habe und es tut, was es muss aber ich nicht, wie verstehen.

Ich definiere während Schleifen als:

(define (while test body) 
    (if (test) 
     (begin 
     (body) 
     (while test body)) 
     (void))) 

Jetzt muss ich ein Programm schreiben, das einer bestimmten Prozedur zu jedem Element einer wandelbaren Liste gilt.

Hier ist, was ich schrieb:

(define (mlist-map-while f x) 
    (while (lambda() (not (null? x))) 
    (lambda() 
     (set-mcar! x (f (mcar x))) 
     (set! x (mcdr x)))) 
    (void)) 

So

list1 (mlist 1 2 3) 

Definition und

(mlist-map-while (lambda (x) (+ x 1)) list1) 

wir '(2 3 4) erhalten Anwendung.

Die Sache, die ich nicht verstehe, ist, wie das erste Element der Liste drin bleibt, denn wenn es fertig ist, wie ich hier

schrieb
(set! x (mcdr x)) 

das erste Verfahren, das -mcar! setzt nutzlos sein muss und seine überlappte mit dem zweiten. Wie in diesem Beispiel:

(define list1 (mlist 1 2 3)) 
(set-mcar! list1 9) 
(set-mcdr! list1 (mcdr list!)) 

und uns fehlt das erste Element, aber dieses Programm lässt es irgendwie und gibt die gewünschte Ausgabe. Ich würde gerne wissen, wie es funktioniert und ob es eine andere Möglichkeit gibt, die angegebene Liste zu durchlaufen.

Antwort

0

Es gibt einen großen Unterschied zwischen set-cdr! und set!. Der erste Abspaltungen der cdr Zeigerpaar, während die letzteren ändert somit die Bindung, was der Name sollte zeigen.

In Ihrem mlist-map-while die Variable x ändert die car, ändert sich dann, was xstellt, die cdr von x zu sein. Es nie ändert sich die cdr so Ihre Bindung list1 immer auf dem ersten Paar während x auf das erste, dann die zweite, etc ...

So ist es mehr wie folgt aus:

(define list1 (mlist 1 2 3)) 
(define list1-ref list1)  ; variable pointing to the same value as list1 
(set-mcar! list1-ref 9)  ; set-car! changes the pair 
(set! list1-ref (mcdr list)) ; set! updates what list1-ref points to 
list1 ; ==> (9 2 3) 
list-ref ; ==> (2 3) 

Sie können eine Liste, in der gleichen Art und Weise durchlaufen, ohne set! zu verwenden, mit Rekursion:

(define (fold function init lst) 
    (if (null? lst) 
     init 
     (fold function 
      (function (car lst) init) 
      (cdr lst)))) 

(fold + 0 '(1 2 3) 
; ==> 6 

(fold cons '() '(1 2 3)) 
; ==> (3 2 1) 

Beachten Sie, dass wir hier Rekursion und ändern, was 012.305.ist die cdr. Jede Rekursion hat seine eigene lst, die mit dem Anrufer eigenen werden soll, nicht zu verwechseln. tut das gleiche wie set! in Ihrem Beispiel, ohne Mutation Es endet. So bedeutet

+0

ist es, wenn ich list1-ref wie in Ihrem Beispiel ((Set definieren!list1-ref (mcdr-Liste))) die Werte 2 und 3 zeigen noch auf den zweiten und dritten Wert von list1? Und wenn ich sie ändere, werden die Werte von list1 jeweils geändert? – Dmitrii

+0

Ja. Aufgrund der Art und Weise, wie eine Liste modelliert wird, hat jedes Elementpaar ein Element und eine Verknüpfung zum Rest der Liste. '(mlist 1 2 3)' ist das gleiche wie '(mcons 1 (mcons 2 (mcons 3 '()))) – Sylwester

+0

Scheme hat TCO-Garantie obwohl ... Sayin'. –