2012-04-17 7 views
9
(do ((n 0 (1+ n)) 
    (cur 0 next) 
    (next 1 (+ cur next))) 
    ((= 10 n) cur))) 

Dies ist ein Beispiel von Lisp Lehrbuch über Schlüsselwort ist "do"Common Lisp tun Makro-Syntax Das Verständnis

die "do" grundlegende Vorlage ist:

(do (variable-definitions*) 
    (end-test-form result-form*) 
statement*) 

Aber für dieses Beispiel, es ist mir ist nicht klar, welcher Teil welcher ist. Und was machen die mittleren 2 Zeilen?

Vielen Dank!

+3

AFAIR, "do" ist ein Makro. – zvrba

Antwort

8

Ihre gute Einbuchtung ergibt:

(do ((n 0 (1+ n)) 
    ^(cur 0 next) 
    |(next 1 (+ cur next))) 
    | 
    +-- first argument of do 

    ((= 10 n) cur))) 
    ^
    | 
    +-- start of second argument of do 

Schauen Sie, sie in einer Reihe aufstellen schön, und das innere Material ist zerklüftet:

((n 0 (1+ n)) 
    (cur 0 next) 
    (next 1 (+ cur next))) 
    ^
    | 
    +- inner material of argument: three forms which are 
     indented by 1 character and aligned together. 

Ihr do kein drittes Argument hat es: es gibt keinen Körper s Aussagen (leere Schleife).

23
(do ((n 0 (1+ n)) ;declares n, initially 0, n+1 each subsequent iteration) 
    (cur 0 next) ;declares cur, initially 0, then old value of next 
    (next 1 (+ cur next))) ;declares next, initially 1, then the sum of (the old) cur and next 
    ((= 10 n) ;end condition (ends when n = 10) 
    cur) ; return value 
    ;empty body 
) 

übersetzen in c-like Code

for(n=0, cur=0, next=1 ; 
    !(n == 10) ; 
    n=old_n+1, cur=old_next, next = old_cur + old_next) 
{ 
    //do nothing 
    old_n = n; 
    old_cur = cur; 
    old_next = next; 
} 
return cur; 

übrigens sollten Sie in der Lage sein, zu sehen, dass dieser Code gibt den 10. Fibonacci-Zahl


Optional EBNF/formale Syntax:

Die Syntax gemäß der Hyperspec ist:

(do ({var | (var [init-form [step-form]])}*) 
    (end-test-form result-form*) 
    declaration* 
    {tag | statement}*) 

Dies zu verstehen erfordert Kenntnisse über EBNF und große Brocken des Hyperspec

+1

großartige Idee, C-Übersetzung zu zeigen, mit 'Old_' Vars, um parallele Zuweisung zu simulieren!Nur zur Auswahl: Ihr Lisp-Code ist falsch ausgerichtet und hat eine zusätzliche schließende Klammer; Ihrem C-Code fehlt das abschließende Semikolon. :) –

+0

Betrachtet man diese Übersetzung, ist es richtig zu sagen, dass das Do-Makro eher eine imperative Programmierung als eine funktionale Programmierung ist? –

+1

@hyh ja und nein --- gemeinsame Lisp ist Multi-Paradigma, und dies ist ein iteratives Konstrukt, das Variablen aktualisiert, was sicherlich unerlässlich ist. Diese Form gibt jedoch einen Wert zurück, so dass Sie diese Schleife als Rückgabewert oder als Bedingung in der if-Anweisung verwenden könnten (zB '(if (> (this-fib-loop) 10) 'gt-10' lte-10)) ') das ist mehr funktional – tobyodavies

0
(do ((n 0 (1+ n)) 
    (cur 0 next) 
    (next 1 (+ cur next))) 
    ((= 10 n) cur)) 

tun hat 3 Teil.

  1. Variable
  2. Abbruchbedingung
  3. Körper

In diesem speziellen Beispiel gibt es keinen Körper. Alles echte Arbeit von 1. und 2. Zuerst richten Sie 3 vars ein und geben Initialwert und Schrittform an. Z.B. n auf 0 gesetzt und während jeder Iteration es weiter die Schritte: (1+ n) die die Bedingung n

das Terminate inkrementieren werden ((= n 10) cur) ist: wenn n gleich 10. Da die cur wie der gesamte Rückgabewert dieses do Ausdrucks zurück.

all diese kombinieren, in diesem do Beispiel wird es von 1 bis 10 zusammenzufassen, die der Teil ist, das zeigt deutlich, 55

+2

es ist' result-form-n' nicht 'action-n' auch der zweite Codeblock ist schlecht eingerückt. – tobyodavies

+1

haben Sie dort viele Klammern verpasst. Außerdem berechnet dies die Folge "(cur, next) = (0,1) (1,1) (1,2) (2,3) (3,5) (5,8) (8,13). .' von Fibonacci-Zahlen, nicht nur Teilsumme. –

+0

@tobyodavies du hast Recht. mein Fehler. – juanitofatas