Nareszcie zaczynam rozumieć ten język! :) Po raz kolejny prawdą okazuje się, że programowanie wchodzi mi do głowy dyskretnie, a nie ciągle. A jak nie chce coś wejść do głowy - odłożyć na pół roku, a potem samo wejdzie :)
(defun znajdz-maksa (X MAKS)
(setq MX MAKS)
(setq N (list-length X))
(if (= N 1) MX
(if (>= MX (second X))
(znajdz-maksa (rest X) MX)
(znajdz-maksa (rest X) (second X)))))
To oczywiście nie jest jakiś trudny kod, ale kurcze! Wyszedł spod moich paluchów! No i notacja polska przestaje być utrudnieniem, a zaczyna mi się nawet podobać.
weosły kosiarz powiedział(a),
28 października 2009 o 18:57:46
Ja tam skłądni jeszcze nie ogarniam. Masz jakiś fajny tutorial?
28 października 2009 o 19:06:33
http://www.cs.sfu.ca/CC/310/pwfong/Lisp/1/tutorial1.html
No i jeszcze bardzo polecam google books. Można tam znaleźć prawdziwe czarne kruki w rodzaju:
http://books.google.pl/books?id=cB8aBXDTqPIC&printsec=frontcover&source=gbs_navlinks_s
:)
28 października 2009 o 20:43:13
Chyba białe kruki? :D
28 października 2009 o 23:45:48
Chyba tak. :P
29 października 2009 o 09:40:05
Bleee, kiepski kod. Pominę brak wcięć, który znacznie utrudnia czytanie. Po pierwsze, jeżeli chcesz mieć zmienne lokalne, użyj LET:
CL-USER> (let ((x 3) (y 5)) (format t "~D + ~D = ~D~%" x y (+ x y))) 3 + 5 = 8Po drugie, twoja funkcja działa w złożoności kwadratowej - niepotrzebnie liczysz długość listy - obliczenie długości listy to Theta(n) względem długości listy. Szybszym rozwiązaniem byłoby posortowanie listy i wzięcie pierwszego elementu. Jeżeli chcesz sprawdzić czy lista jest pusta, użyj ENDP:
I teraz dwa rozwiązania Twojego problemu, tym razem w O(n). Pierwsze, podobne do Twojego, ale napisane bardziej elegancko, wygląda tak:
CL-USER> (defun find-max (list) (labels ((max-finder (list max) (if (endp list) max (max-finder (rest list) (if (> (first list) max) (first list) max))))) (max-finder (rest list) (first list)))) FIND-MAX CL-USER> (find-max (list 1 7 3 4 9 12 4 8)) 12Zalety: -rekurencja ogonowa sprawia, że większość kompilatorów zoptymalizuje zużycie pamięci -lepsza złożoność -bardziej funkcyjny, mniej imperatywny -czytelniejszy kod
Wady: nieco dłuższy kod.
Teraz drugie rozwiązanie. W standardowej bibliotece jest funkcja MAX, która zwraca największy ze swoich argumentów. Aby znaleźć największy element listy, można ją wykorzystać w następujący sposób:
CL-USER> (defun find-max2 (list) (reduce #'max list)) FIND-MAX2 CL-USER> (find-max2 (list 8 3 4 6 0 123 53 2)) 123I po problemie. Krótki kod, złożoność liniowa.
Polecam lekturę "On Lisp" Paula Grahama, pokazuje m.in., jak pisać elegancki i zwięzły kod w CL.
29 października 2009 o 11:59:48
A ja tam przedkładam car/cdr nad first/rest.
29 października 2009 o 12:00:56
Ja też, ale już nie chciałem autorowi mieszać. :)
01 listopada 2009 o 20:03:36
OK :) Nastąpiło małe nieporozumienie. Oczywiście to co napisaliście jest prawdą. Tyle, że moja funkcja powstała raczej jako odprysk zadania z programowania w Javie (a dokładnie - napisz schemat blokowy programu znajdującego największą z liczb, który to program większość mojej grupy wykonała ogromnym drzewem if-else). I jako taki spełnia swoje zadanie :P
Ale oczywiście dzięki za info, szczególnie za "On Lisp" i rekurencję ogonową. Natomiast używanie car i cdr uważam za rodzaj lansu (większy nawet niż opisywanie swoich mini funkcji lispowych na blogu :)), ale to tylko moja skromna opinia.
01 listopada 2009 o 20:08:09
Wiesz, schematy blokowe kiepsko pasują do funkcyjnego paradygmatu programowania, nic więc dziwnego, że próba przepisania go do języka funkcyjnego poskutkowała narodzeniem potworka.
A car/cdr to kwestia tradycji, ma to też inne zalety - patrz funkcje CAAR, CADR i podobne, jak by to wyglądało dla FIRST i REST? FIRST-OF-FIRST? REST-OF-FIRST? Nieco zbyt verbose, nawet jak na Lispowe standardy.
"On Lisp" to książka, która sprawiła, że pokochałem Lisp :)
01 listopada 2009 o 20:10:54
Aha, zapomniałem - z książek dostępnych na sieci polecam też Practical Common Lisp, SICP (to akurat o Scheme i przynudne, gdy się wie już trochę więcej), PAIP i AMOP (po przeczytaniu AMOP człowiek się dziwi, że to, co ma Java/C++, ludzie nazywają obiektowością).
01 listopada 2009 o 20:14:46
Też zauważyłem, że lisp i schematy jakoś się do siebie nie kleją :)
caar i cadr - zwracam honor - zupełnie zapomniałem o tej właściwości, choć ja zdążyłem się już przyzwyczaić do first, second, third.
Ale skoro już tu jesteś mam kilka pytań, jeśli nie masz nic przeciwko :)
1) Czy lisp nadaje się do programowanie aplikacji z graficznym interfejsem i jeśli tak to jak to jest zorganizowane?
2) Czy możesz polecić jakiś tutorial, ew. chociaż naprowadzić mnie na coś związanego z programowaniem w lisp aplikacji internetowych? Czy coś takiego jest w ogóle praktykowane i opłacalne? (Rozumiem, że znalezienie darmowego hostingu na taki tandem -> 0 ?) :)
01 listopada 2009 o 20:20:18
1) Nadaje się nie gorzej niż dowolny inny język, to tylko kwestia bibliotek, których jest raczej mało. Polecam googlowanie CLIM i w ogóle przejrzenie cliki (http://cliki.net)
2) google: uncommon web, kpax, hunchentoot, zajrzyj też na http://www.cliki.net/web
darmowe hostingi się i tak do niczego nie nadają, nawet te php/mysql.