2013-05-04 5 views
5
(define .. 
    (lambda (start stop) 
    (cond ((> (add1 start) stop) (quote())) 
      ((eq? (add1 start) stop) (sub1 stop)) 
      (else (cons start (.. (add1 start) stop)))))) 

Ich habe eine einfache Bereichsfunktion definiert. Die Absicht ist fürRekursiver Bereich in Lisp fügt einen Punkt hinzu?

(.. 1 5) --> (1 2 3 4) 

Stattdessen wird eine bizarre Periode meiner Tupel hinzugefügt wird, und ich habe keine Ahnung, warum:

(.. 1 5) --> (1 2 3 . 4) 

Ich verstehe nicht, warum dies geschieht. Jede Hilfe ist willkommen

+0

Welcher Fall im 'cond' wird verwendet, wenn Sie' (.. 1 2) '? Was gibt es zurück? – Barmar

Antwort

15

Eine Liste in Schema ist entweder die leere Liste () (auch als nil in einigen Lisps bekannt) oder eine cons Zelle, deren car (auch als first bekannt) ist ein Element der Liste und deren cdr (auch bekannt als rest) ist entweder der Rest der Liste (dh eine andere Liste) oder ein Atom, das die Liste beendet. Der herkömmliche Terminator ist die leere Liste (); Listen, die mit () enden, werden als "richtige Listen" bezeichnet. Listen, die von einem anderen Atom beendet werden, werden als "unsachgemäße Listen" bezeichnet. Die Liste (1 2 3 4 5) enthält die Elemente 1, 2, 3, 4 und 5 und wird durch () abgeschlossen. Man könnte es konstruieren, indem

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5()))))) 

Nun, wenn das System druckt eine cons Zelle, der allgemeine Fall ist es zu drucken, indem

(car . cdr) 

Zum Beispiel wird das Ergebnis (cons 1 2) als

gedruckt

Da Listen aus Cons-Zellen bestehen, können Sie diese Notation auch für Listen verwenden:

obwohl
'(1 2 3 4 5) == 
'(1 . (2 . (3 . (4 . (5 .()))))) 

die eher klobig ist, so dass die meisten lisps (alle, die ich kenne) einen speziellen Fall haben für cons Zellen Druck: Wenn die cdr ist eine Liste (entweder eine andere Nachteile Zelle oder ()), dann don‘ t drucken Sie die ., und drucken Sie nicht die umgebende Klammer der cdr (die es sonst hätte, da es eine Liste ist). Also, wenn Sie ein Ergebnis wie

(1 2 3 . 4) 

sehen es bedeutet, dass Sie eine falsche Liste haben, die durch das Atom 4 beendet. Es hat die Struktur

(1 . (2 . (3 . 4))) 

Jetzt ist die Frage: Wo in Ihrem Code ist die Listenkonstruktion schief gegangen?.. immer soll eine richtige Liste zurückzukehren, einen Blick auf die Fälle sehen lassen: Der erste Fall gibt immer eine richtige Liste (die leere Liste):

((> (add1 start) stop) (quote())) 

Der zweite Fall sieht aus wie es etwas zurückgeben kann, der nicht ist Liste (unter der Annahme, dass (sub1 stop) == (- stop 1)):

((eq? (add1 start) stop) (sub1 stop)) 

Nun, wenn .. richtig funktioniert, dann der dritte Fall wäre immer eine richtige Liste zurückkehrt (da (cons x y) eine richtige Liste ist, wenn y ist):

(else (cons start (.. (add1 start) stop))) 

Machen Sie Ihren zweiten Fall eine Liste zurück und Sie sollten alle eingestellt sein.

+0

Vielen Dank für Ihren Rat - die Erklärung war klar und einfach zu verstehen. – vim

1

Ihr Ausdruck (sub1 stop)(list (sub1 stop))

Damit cons lesen muss eine richtige Liste aufzubauen, muss das zweite Element eine Liste selbst sein. Daher sollte Ihre Funktion .. eine Liste eines Typs für jede cond-Klausel zurückgeben.

1

Entfernen dieses Teil des cond

((eq? (add1 start) stop) (sub1 stop)) 

Es ist ein vorzeitigen Abgang verursacht.

+0

+1. weniger ist mehr !!! :) :) –

Verwandte Themen