2009-09-06 10 views
7

Jestem nowy w seplenieniu i piszę kilka prostych programów, aby lepiej się z nim zapoznać. Jedną z rzeczy, które robię, jest pisanie rekursywnej i iteracyjnej wersji metody czynnikowej. Jednak natknąłem się na problem i nie mogę go rozwiązać.Ostrzeżenie Lispa: xx nie jest zadeklarowane ani powiązane, będzie traktowane tak, jakby zostało zadeklarowane SPECJALNE

Widziałem podobny błąd na Lisp: CHAR is neither declared nor bound , ale rozwiązanie nie zostało faktycznie osiągnięte, inne niż PO zdał sobie sprawę, że popełnił "błąd pisania". W REPL mogę używać funkcji setf i działa dobrze. Używam również LispBox z emacs. Byłbym wdzięczny za wszelkie sugestie!

(defun it-fact(num) 
    (setf result 1) 
    (dotimes (i num) 
    (setf result (* result (+ i 1))) 
) 
) 

UWAGA w IT-FACT: wynik jest ani uznane ani związana, będzie traktowana tak, jakby zostały uznane specjalnych.

+1

Zobacz http://www.cs.cmu.edu/Groups/AI /html/faqs/lang/lisp/part1/faq-doc-4.html, szczególnie przykład "DOBRY:". Ludzie tutaj są całkiem przyjaźni, ale kod jest łatwiejszy do odczytania, jeśli jest wcięty bardziej jak typowy kod Lispa. Twoje zdrowie! – Alec

Odpowiedz

5

Trzeba powiązać zmiennej „wynik” - za pomocą „pozwolić” na przykład - przed uruchomieniem z niego korzystać:

(defun it-fact(num) 
    (let ((result 1)) 
    (dotimes (i num) 
     (setf result (* result (+ i 1)))))) 

w celu uzyskania dalszych informacji może chcesz przeczytać this ...

+0

Och, widzę. Próbowałem wcześniej "wypuścić", ale użyłem go tak, jakby był setf, i nie zawarłem pętli kropek w nawiasie let. Myślę, że ma to związek z zasięgiem lub czymś. Dzięki za pomoc dla wszystkich! – Aaron

+0

Poważnie, wprowadź prawidłowo swój kod. –

+0

Ponieważ jestem przede wszystkim programistą java, możesz łatwo zobaczyć, dlaczego usunąłem nawias (oglądając je jako nic więcej niż nawiasy klamrowe). Odkąd przyzwyczaiłem się do zamykania rodzicielskich wierszy w jednym wierszu, dzięki zaprezentowanym tutaj przykładom, jest to "poważnie", a nie tak wielka sprawa. Dzięki anway :) – Aaron

5

W Lispie zmienne lokalne muszą być jawnie zadeklarowane za pomocą LET lub innych formularzy, które tworzą zmienne lokalne. To różni się od np. Python lub JavaScript gdzie przypisanie zmiennej tworzy zmienną w bieżącym zakresie leksykalnym.

Twój przykład może być zapisane tak:

(defun it-fact(num) 
    (let ((result 1)) 
    (dotimes (i num) 
     (setf result (* result (+ i 1)))))) 

Off-topic Komentarz: nie ma sensu wprowadzanie zamykających nawiasów na oddzielnych liniach.

6

Istnieje kilka rzeczy źle lub nie tak dobre Lisp styl:

(defun it-fact(num)      ; style: use a space before (
    (setf result 1)      ; bad: variable result is not introduced 
    (dotimes (i num) 
    (setf result (* result (+ i 1)))  ; bad: extra addition in each iteration 
)          ; style: parentheses on a single line 
)          ; bad: no useful return value 

Możliwa wersja:

(defun it-fact (num) 
    (let ((result 1))      ; local variable introduced with LET 
    (loop for i from 1 upto num   ; i starts with 1, no extra addition 
     do (setf result (* result i))) 
    result))        ; result gets returned from the LET 
+2

Dzięki za sugestie! Tak, zdałem sobie sprawę, że czasy zaczynały się od 0 i gdybym nie zwiększył tego w mnożeniu, zawsze zwracał 0 ... Twoja pętla wydaje się łatwiejsza do odczytania. Myślę, że umieszczam nawiasy w każdym wierszu, ponieważ wciąż jestem przyzwyczajony do nawiasów klamrowych z C++/java, ale spróbuję przyjąć twoją praktykę na seplenienie. Ups, tak, przeoczyłem powrót, dziękuję za wskazanie tych rzeczy! – Aaron

Powiązane problemy