2012-02-27 19 views
5

Czy istnieje możliwość sprawdzenia, czy coś jest funkcją częściową w Clojure?Jak mogę sprawdzić, czy funkcja jest częściowa?

Najlepiej mieć coś takiego jak (partial? (partial + 10))?

góry dzięki

+2

Po prostu ciekawy: dlaczego tego potrzebujesz? – viebel

+1

@Yehonathan Wprowadzam Shen w Clojure i tam potrzebuję różnić się między normalnymi funkcjami i częściowymi funkcjami. (Ze względu na decyzje projektowe). –

+0

Co to jest Shen? A co z anonimową funkcją utworzoną przez '#()'? – viebel

Odpowiedz

16

Nie, ponieważ funkcje utworzone przez częściowe to tylko „normalne” funkcje. Można jednak korzystać z niektórych metadanych dla niej tak:

(defn partial2 [f & more] 
    (with-meta (apply partial f more) {:partial true})) 

(def partial-plus (partial2 + 1 2)) 

(meta partial-plus) ;;=> {:partial true} 

naprawdę nie przemyślane konsekwencje takiego podejścia mimo ...

Kotarak wymyślił ładniejszy rozwiązanie, które działa, ale nie zawsze. Na przykład wziąć to:

(partial? (partial + 1)) ;;=> true 
(partial? (partial + 1 2)) ;;=> false 

To działa:

(defn partial? [f] 
    (let [[fst snd] (-> (class f) (.getName) (string/split #"\$"))] 
    (= ["clojure.core" "partial"] [fst snd]))) 

ze stringami/Split będąc Funkcja split z clojure.string (1.3) lub clojure.contrib.str-utils2 (1.2).

+0

clojure.string jest również w wersji 1.2. –

+0

Powinieneś prawdopodobnie testować także dla 'clojure.core', nie tylko" częściowego ". – kotarak

+0

Dobra robota, naprawiłem to. –

2

Funkcje tworzone przez częściowe są po prostu normalnymi funkcjami, ale jeśli jesteś na to nastawiony, może coś takiego może pomóc? :

(defn partial? 
    [f] 
    (clojure.contrib.string/substring? "partial" (str (class f)))) 

Nota prawna: Nie wiem, czy coś takiego jest głupie.

5

Możesz za pomocą hackera.

user=> (let [partial-classes (map class [(partial + 1) 
             (partial + 1 2) 
             (partial + 1 2 3) 
             (partial + 1 2 3 4)])] 
     (defn partial? 
      [x] 
      (some #(instance? % x) partial-classes))) 
#'user/partial? 
user=> (partial? (partial - 1)) 
true 
user=> (partial? (partial - 1 2)) 
true 
user=> (partial? (partial - 1 2 3)) 
true 
user=> (partial? (apply partial - 1 2 [3 4 5])) 
true 

EDIT: Poprawiono zgodnie z komentarzem Michiel użytkownika. To, że musisz znać innards of partial, potwierdza hackowatą naturę.