2013-06-16 10 views
16

Ponieważ argumenty funkcji Common Lisp oceniają w kolejności od lewej do prawej, to dlaczego nie wykorzystać zwykłą funkcję:Common Lisp: Dlaczego progn jest specjalną formą?

(defun progn2 (&rest body) 
    (first (last body))) 

zamiast specjalnego formularza?

+1

Czy "defun" nie zawiera już niejawnego 'progn'? Sprawdź makro rozszerzenia 'defun'. – tuscland

+5

Zarówno odpowiedzi @sds, jak i @ RainerJoswig stanowią ważne punkty. Odpowiedź "wartości" w @ sds jest czymś, co możesz złapać raz na jakiś czas, a zachowanie opisane przez @RainerJoswig jest bardzo ważne, szczególnie gdy zaczniesz umieszczać makrowe formularze najwyższego poziomu w swoim źródle; jeśli wytwarzają więcej niż formę, która powinna być traktowana jako najwyższy poziom, potrzebujesz 'progn'. –

Odpowiedz

24

Istnieje również inna cecha PROGN których nie można uzyskać za pomocą funkcji:

Imagine ten kod w pliku kodu Common Lisp:

(progn 
    (defmacro foo())) 

vs.

(my-progn 
    (defmacro foo())) 

Przy użyciu PROGN kompilator potraktuje formularz DEFMACRO jako formularz najwyższego poziomu. Oznacza to na przykład, że kompilator zauważa, że ​​istnieje definicja makra i udostępnia ją w środowisku kompilacji .

Za pomocą funkcji MY-PROGN kompilator nie rozpoznaje formularza DEFMACRO, ponieważ nie znajduje się na najwyższym poziomie.

+3

Co oznacza "forma najwyższego poziomu"? – 1ambda

22

progn zwraca wszystkie wartości z ostatniego formie ocenia, Twój funkcja zwraca tylko pierwsza:

(progn (values 1 2 3)) 
=> 1, 2, 3 
(progn2 (values 1 2 3)) 
=> 1 

Innym istotnym elementem progn (wspomniane przez Rainer pierwszego) jest to, że zachowuje wszystkie swoje formy top-level , co umożliwia makrom rozwijanie się do postaci wielu (patrz np. moja odpowiedź na "“value returned is unused” warning when byte-compiling a macro").