ouzo.jogger.pl

<- Powrót 28 października 2009

LIeeeeSP!!!

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

Dodano w kategorii Ogólne Prywatne o 18:33:43, Pokaż wyszystkie wpisy

Komentarze »

  1. weosły kosiarz powiedział(a),

    28 października 2009 o 18:57:46

    Ja tam skłądni jeszcze nie ogarniam. Masz jakiś fajny tutorial?

  2. aevin powiedział(a),

    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

    :)

  3. Trobin powiedział(a),

    28 października 2009 o 20:43:13

    Chyba białe kruki? :D

  4. aevin powiedział(a),

    28 października 2009 o 23:45:48

    Chyba tak. :P

  5. Dodek powiedział(a),

    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 = 8
    

    Po 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:

    CL-USER> (endp (list 1 2 3))
    NIL
    CL-USER> (endp '())
    T
    

    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))
    12
    

    Zalety: -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))
    123
    

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

  6. hcz powiedział(a),

    29 października 2009 o 11:59:48

    A ja tam przedkładam car/cdr nad first/rest.

  7. Dodek powiedział(a),

    29 października 2009 o 12:00:56

    Ja też, ale już nie chciałem autorowi mieszać. :)

  8. aevin powiedział(a),

    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.

  9. Dodek powiedział(a),

    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 :)

  10. Dodek powiedział(a),

    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ą).

  11. aevin powiedział(a),

    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 ?) :)

  12. Dodek powiedział(a),

    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.