2016-06-17 10 views
1

Ich habe eine Methode, in der ich eine leere Liste erstellen, einige Werte anhängen und dann diese Liste zurückgeben möchte. Meine Methode gibt eine leere Liste zurück. Was mache ich falsch?Erstellen und Zurückgeben einer Liste in einer Methode in Scheme

(define-struct graph (vertices edges)) 
(define-struct vertice (name visited)) 
(define-struct edge (start-vertice end-vertice length)) 

;I create data for testing here 
(define vertices-list2 
    (list (make-vertice 0 0) 
     (make-vertice 1 0) 
     (make-vertice 2 0) 
     ) 
) 

(define edges-list2 
    (list (make-edge 0 1 0) 
     (make-edge 1 2 0) 
     ) 
) 

(define (find-adj V edge-list) 
    (let ((ret '())) 
    (cond 
     [(empty? edge-list) ret] 
     [(eq? V (edge-start-vertice (car edge-list))) 
     (begin 
     (append ret '((edge-end-vertice (car edge-list)))) 
     (find-adj V (cdr edge-list))) 
     ] 
     [else (find-adj V (cdr edge-list))] 
    ) 
    ) 
) 

(define G (make-graph vertices-list2 edges-list2)) 
(find-adj 0 (graph-edges G)) 
+0

Alle Wege durch 'find-adj' Ende entweder in einem rekursiven Aufruf zu' find-adj', oder sie geben 'ret' zurück, das gerade zwei Zeilen zuvor an'() 'gebunden wurde. Daher geben alle Aufrufe letztendlich eine leere Liste zurück. – melpomene

+0

Laut https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._append%29%29 gibt 'append' ein neues zurück Liste; Es ändert nicht "ret". Selbst wenn dies der Fall ist, verwenden Sie weder den Rückgabewert von append noch "ret", nachdem "append" aufgerufen wurde. – melpomene

+0

Ich sehe, das macht Sinn. Aber wie kann ich es dann machen, da ich rekursiv find-adj aufrufen muss? Ich möchte eine Liste aller Nachbarn zurückgeben, also muss ich sie irgendwo speichern, wenn ich sie finde, und diese Liste mit jeder Rekursion anhängen. – Arcane

Antwort

2

Es gibt mehrere Fehler in Ihrem Code. Ich habe einige Vorschläge:

  • Sie brauchen kein begin innerhalb eines cond, es ist implizit.
  • Verwenden Sie equal? anstelle von eq?, da es ein allgemeineres Vergleichsverfahren ist.
  • Sie müssen eigentlich zuweisen oder übergeben Sie als Parameter den Wert von append zurückgegeben, sonst machst du einen leeren Vorgang.
  • Stellen Sie sicher, Anrufedge-end-vertice, Sie waren einfach eine Liste von Symbolen anhängen, nicht eine Prozedur wegen des Zitats am Anfang aufrufen.
  • Sehr wichtig: die Variable ret darf NICHT bei jedem Aufruf der Prozedur neu deklariert werden, sonst überschreiben Sie das Ergebnis bei jedem Aufruf.

Denken Sie daran, dass append und alle anderen Listen-Operationen ändern die Liste nicht an Ort und Stelle, sie eine neue Liste nur zurückgeben - und wenn Sie speichern Sie es nicht oder es passieren um als Parameter (das wäre in diesem Fall bevorzugt), verlieren Sie die Änderung. Und es ist besser, wenn Sie ret als Parameter übergeben, so dass ihr Wert zwischen Anrufen gehalten wird - wir einen Helfer Verfahren für das definieren:

(define (find-adj V edge-list) 
    (define (helper edge-list ret) 
    (cond 
     [(empty? edge-list) ret] 
     [(equal? V (edge-start-vertice (car edge-list))) 
     (helper (cdr edge-list) 
       (append ret (edge-end-vertice (car edge-list))))] 
     [else (helper (cdr edge-list) ret)])) 
    (helper edge-list '())) 
+0

Nochmals vielen Dank für Ihre Hilfe, ich schätze es wirklich. Dieser Code funktioniert jedoch nicht für mich. Ich bekomme Fehler: 'define: erwartet nur einen Ausdruck für den Funktionskörper, aber gefunden 1 extra part' – Arcane

+0

@Arcane entweder die Sprache zu etwas fortgeschrittener ändern (vorzugsweise verwenden Sie' #lang Schläger '), oder extrahieren Sie den inneren Helfer als a separate Prozedur, übergibt 'V' auch als Parameter –

+0

so gibt es keinen Weg, während "Advanced Student" Einstellungen verwenden? – Arcane