2011-08-13 7 views
6

Próbuję rozwiązać ćwiczenie z sekwencją z ćwiczeniem pod numerem 4clojure.com. Ćwiczenie polega na zliczaniu liczby elementów w kolekcji bez użycia funkcji count.Jak mogę wywołać recur w warunkowym w Clojure?

Pomyślałem, że mogę to zrobić poprzez rekursję, przez użycie rest. Jeśli to, co otrzymam, nie jest puste, zwracam 1 + recur on the sequence rest returned. Problem polega na tym, że w końcu się

java.security.PrivilegedActionException: java.lang.UnsupportedOperationException: 
Can only recur from tail position 

chociaż Dzwonię recur jako ostatniej deklaracji.

(fn [coll] (let [tail (rest coll)] 
      (if (empty tail) 
       1 
       (+ 1 (recur tail))))) 

Czy czegoś brakuje?

Odpowiedz

8

Ostatnie oświadczenie jest dodatkiem, a nie numerem telefonu recur, dlatego też nie działa. To, że jest w środku, nie ma z tym nic wspólnego. (fn [coll] (let [tail (rest coll)] (+ 1 (recur tail)))) również nie działa.

Zwykły sposób przekształcenia takiej funkcji w rekursywny ogon ma na celu sprawienie, aby funkcja wzięła drugi argument, który trzyma akumulator dla wartości, którą dodajesz, a następnie powtarza się tak: (recur tail (+ acc 1)) zamiast próbując dodać 1 do wyniku recur.

Zgodnie z ogólną zasadą: jeśli cokolwiek robisz dla wyniku recur (jak na przykład dodanie do niego 1), nie może być w pozycji ogonowej, więc nie będzie działać.

6

Błąd, który otrzymujesz, wskazuje, że końcowe wyrażenie (+ 1 (recur tail)) nie jest optymalizowane pod kątem optymalizacji połączeń (czy to jest słowo?). Problem polega na tym, że musi on zachować liczbę wyrażeń (+ 1 ...) na stosie, aby ocenić wynik tej funkcji. Optymalizacja wywołania ogona może wystąpić tylko wtedy, gdy wartość wywoływanej funkcji jest potrzebna, aby znać zwrot funkcji wywołującej połączenie.

To, co próbujesz napisać, to właściwie fold. W takim przypadku funkcja powinna przejść do końca reszty kolekcji, jak również do liczenia do tej pory.

(fn [count coll] (let [tail (rest coll)] 
    (if (empty tail) 
     count 
     (recur (+ 1 count) tail))))) 
Powiązane problemy