2010-03-08 8 views
10

Zastanawiam się, czy istnieje standardowa praktyka dotycząca używania etykiet w Lisp. Wprowadziłem w życie implementację algorytmu Lisp opisaną w pierwszej odpowiedzi tutaj. Generating permutations lazily Moja aktualna wersja używa etykiet do rozbicia części funkcji.Lisp Style funkcje lokalne etykiety pytanie czy nie?

(defun next-permutation (pmute) 
    (declare (vector pmute)) 
    (let ((len (length pmute))) 
    (if (> len 2) 
     (labels ((get-pivot() 
        (do ((pivot (1- len) (1- pivot))) 
         ((or (= pivot 0) 
          (< (aref pmute (1- pivot)) 
           (aref pmute pivot))) 
         pivot))) 
       (get-swap (pivot) 
        (let ((swp (1- len))) 
        (loop for i from (1- len) downto pivot do 
          (if (or (and (> (aref pmute i) 
              (aref pmute (1- pivot))) 
             (< (aref pmute i) (aref pmute swp))) 
            (< (aref pmute swp) (aref pmute (1- pivot)))) 
           (setf swp i))) 
        swp)) 
       (next (swp pivot) 
        (rotatef (aref pmute (1- pivot)) (aref pmute swp)) 
        (reverse-vector pmute pivot (1- len)))) 
      (let ((piv (get-pivot))) 
      (if (> piv 0) 
       (next (get-swap piv) piv) 
       nil)))))) 

Ponieważ każda etykieta jest wywoływana tylko raz zastanawiałem się, czy to jest uważane za złą praktyką, ponieważ jedyny powód, aby zrobić to w tym przypadku ze względów estetycznych. Twierdzę, że obecna wersja z etykietami jest bardziej przejrzysta, ale może to być sprzeczne z powszechną mądrością, której nie jestem świadomy, będącą nowością w Lisp.

+1

Możesz użyć 'flet' zamiast' labels', jeśli twoje funkcje nie muszą się nawzajem odwoływać (lub siebie). – Svante

+0

Czy jest jakaś korzyść z tego powodu, oprócz przekazywania tych dodatkowych informacji innym osobom czytającym kod? – asm

+0

Prawdopodobnie nie. Pamiętaj jednak, że powinieneś napisać kod dla kolejnej osoby czytającej kod, a kompilator/tłumacz nie jest Twoją podstawową publicznością. – Vatine

Odpowiedz

7

Nie, w porządku. Zapisywanie nazwanych funkcji sprawia, że ​​kod jest trochę bardziej samokomponowany i bardziej modułowy.

Czasami chciałbym również listę wszystkich zmiennych używanych w funkcji arglist i nie używać zmiennych z funkcji otaczającej. To sprawia, że ​​interfejs jest trochę bardziej przejrzysty i pomaga przenieść funkcję w kodzie (jeśli to konieczne).

Lokalne funkcje oferują również możliwość dodawania lokalnych ciągów dokumentacji i opisów interfejsów.

Jeśli funkcje lokalne stają się zbyt duże i mogą być również używane na zewnątrz, wówczas wyodrębniam je i sprawię, że będą globalne.

1

Nie będąc niczym innym niż nowicjuszem Lisp, powiedziałbym, że postępujesz słusznie: sprawić, by twój kod był bardziej czytelny poprzez nazywanie fragmentów.

2

Nie widzę w tym nic złego. Tworzysz dwa podprocesy bardzo jasne i łatwe do porcjowania, dzięki czemu łatwo jest szybko zorientować się, jaka funkcja naprawdę działa, patrząc tylko na ciało. Również teraz łatwo jest promować wewnętrzne funkcje do funkcji globalnych, jeśli potrzebujesz.