Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check if function is a partial?

Is there a possibility to check if something is a partial function in Clojure?

It would be best to have something like (partial? (partial + 10)) ?

Thanks in advance

like image 912
Dominik G Avatar asked Feb 27 '12 11:02

Dominik G


2 Answers

No, because functions created by partial are just "normal" functions. You could however use some metadata for it, like this:

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

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

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

Haven't really thought through the consequences of this approach though...

Kotarak came up with a nicer solution that works, but not always. For example take this:

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

This works:

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

with string/split being the split function from clojure.string (1.3) or clojure.contrib.str-utils2 (1.2).

like image 189
Michiel Borkent Avatar answered Sep 22 '22 17:09

Michiel Borkent


You can with a hack.

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: Fixed according to Michiel's comment. That you have to know the innards of partial confirms the hacky nature.

like image 28
kotarak Avatar answered Sep 19 '22 17:09

kotarak