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

To jest przykład z Lisp podręcznika na temat słów kluczowych „zrobić”Zrozumienie Common Lisp zrobić makro składnię

„zrób” podstawowy szablon jest:

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

Ale na tym przykładzie, że to nie jest dla mnie jasne, która część jest która. A także, co robią te środkowe 2 linie?

Dziękujemy!

+3

AFAIR, "do" to makro. – zvrba

Odpowiedz

8

swój dobry wcięcia wyraźnie pokazuje, która część jest który:

(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 

Look, że line up ładnie, a materiał wewnętrzny jest wcięty:

((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. 

Twój do nie ma tam trzeci argument: nie ma ciała s tatements (pusta pętla).

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 
) 

przekłada się na C-jak kod

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; 

notabene powinny być w stanie zobaczyć, że kod ten zwraca 10. liczb Fibonacciego


Opcjonalnie EBNF/składni formalnej:

Składnia zgodnie z Hyperspec jest:

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

Zrozumienie tego wymaga znajomości EBNF i duże kawałki o Hyperspec

+1

świetny pomysł, aby pokazać tłumaczenie C, używając 'old_' vars do symulacji równoległego przypisania!Po prostu, aby wybrać: twój kod Lisp jest źle wyrównany i ma jeden dodatkowy nawias zamykający; twój kod C brakuje średnika końcowego. :) –

+0

Patrząc na to tłumaczenie, czy można słusznie powiedzieć, że makro do wykonania bardziej przypomina programowanie imperatywne zamiast programowania funkcjonalnego? –

+1

@hh tak i nie - zwykłe seplenienie to wieloparadygmat, a to jest iteracyjna konstrukcja, która aktualizuje zmienne, co z pewnością jest konieczne. Jednak ta forma zwraca wartość, więc możesz użyć tej pętli jako wartości zwracanej lub jako warunku w instrukcji if (np. '(If (> (this-fib-loop) 10) 'gt-10' lte-10) '), który jest bardziej funkcjonalny – tobyodavies

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

zrobić ma 3 części.

  1. zmienna
  2. zakończyć warunek
  3. ciała

W tym konkretnym przypadku nie ma ciała. Cała prawdziwa praca wykonana przez 1. i 2. Najpierw ustaw 3 vary i podaj wartość początkową i formę kroku. Na przykład. n ustawiony na 0, a w każdej iteracji jest ponadto kroki: (1+ n), która zwiększa zawartość n

terminate warunku jest ((= n 10) cur): gdy n równa 10. Następnie zwrócić cur w całkowitej wartości powrotnej tego do ekspresji.

Połącz wszystkie te, w tym do przykładzie będzie to suma od 1 do 10, co daje 55

+2

to' result-form-n', a nie 'action-n' również twój drugi blok kodu jest źle wcięty. – tobyodavies

+1

tęskniłeś za wieloma nawiasami. Oblicza to również sekwencję '(cur, next) = (0,1) (1,1) (1,2) (2,3) (3,5) (5,8) (8,13). "liczby Fibonacciego, a nie tylko częściowej sumy. –

+0

@tobyodavies masz rację. mój błąd. – juanitofatas