2011-10-10 12 views
9

Skąd mogę wiedzieć, czy nazwa funkcji podana jako łańcuch może być wywołana czy nie w bieżącym kontekście? coś takiego:Clojure: ustal, czy istnieje funkcja

(callable? "asdasd") ;; false 
(callable? "filter") ;; true 

dzięki

+0

Również zwrócić uwagę na słowo „wpłacone” jest przeciążony jest tutaj. Wszystkie funkcje Clojure to java.util.concurrent.Callables. –

Odpowiedz

17

szukasz determinacji,

(resolve (symbol "asd")) 

zwraca nil

(resolve (symbol "filter")) 

return # 'clojure.core/filter

Aby sprawdzić, czy zmienna jest funkcją (zasługa @amalloy):

(-> s symbol resolve deref ifn?) 
+1

zwraca to, co powiedziałeś, ale jak mogę określić, czy można to wywołać, czy nie? – pistacchio

+0

Możesz wywołać (fn? (Rozwiązać (symbol "filter"))) - Polecam to poprzez moją odpowiedź –

+0

@JoostDiepenmaat: w tym przypadku '(fn? (Eval (symbol" filter ")))' - ' rozwiązać 'zwraca klasę lub var, nie coś z interfejsem' Fn' (zobacz moją odpowiedź), a zatem nie będzie działać. – ffriend

-1
(defn callable? [name]  
    (clojure.test/function? (symbol name))) 

UPD. Sprawdziłem, że fn? sprawdza tylko dla interfejsu Fn i nie działa dla rozpoznanego symbolu. Chociaż, clojure.test/function? robi to, co jest potrzebne, więc zaktualizowałem przykład.

1

Szanse są, jeśli to potrzebne, robisz coś złego, ale ...

(defn callable? 
    [s] 
    (let [obj (try (eval (symbol s)) (catch Exception e))] 
    (and obj (fn? obj)))) 
+4

Augh nr. Używanie 'resolve' oznacza, że ​​możesz robić coś złego; użycie 'eval' do zrobienia tego samego zadania jest pewnym znakiem, że robisz coś złego. – amalloy

Powiązane problemy