clojurefunctional-programming

Why can I use a set as predicate in clojure?


I'm trying to remove an element from a list or set, like this:

(remove :Veronica (list :Veronica :Hailey))

It does not work, so, I went to remove documentation, that says I need to pass a predicate to the remove function. But the following code works:

(remove #{:foo} [:foo :bar])
(remove #{:foo} (list :foo :bar))

#{:foo} is a set. Why does it works?

Is a set a function?

Thanks


Solution

  • Why does the following

    (remove :Veronica (list :Veronica :Hailey))
    ;(:Veronica :Hailey)
    

    A keyword such as :Veronica is a function accepting one argument, hence can be used as a predicate.

    But ...

    For example,

    (:Veronica #{:Veronica})
    ;:Veronica
    
    (:Veronica #{1 2 "Buckle my shoe"})
    ;nil
    

    It also forgives useless arguments:

    (:Veronica 4) ; 4 is not a map or set. 
    ;nil
    

    So (:Veronica :Veronica) and (:Veronica :Hailey) are both nil, so the remove in

    (remove :Veronica (list :Veronica :Hailey))
    

    ... accomplishes nothing, since the predicate always evaluates false(ish).


    The other solutions explain why

    (remove #{:foo} (list :foo :bar))
    

    ... has the effect you are looking for.