Clojure

Add more type predicate fns to core

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: Release 1.5, Release 1.6
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Add more built-in type predicates:

1) Definitely missing: (atom? x), (ref? x), (deref? x), (named? x), (map-entry? x), (lazy-seq? x).
2) Very good to have: (throwable? x), (exception? x), (pattern? x).

The first group is especially important for writing cleaner code with core Clojure.

Activity

Hide
Alex Miller added a comment -

I don't think it's worth making a ticket for this until Rich has looked at it and determined which parts are wanted.

Show
Alex Miller added a comment - I don't think it's worth making a ticket for this until Rich has looked at it and determined which parts are wanted.
Hide
Brandon Bloom added a comment -

I'd be happy to provide a patch for this, but I'd prefer universal interface support where possible. Therefore, this ticket, in my mind, is behind http://dev.clojure.org/jira/browse/CLJ-803 etc.

Show
Brandon Bloom added a comment - I'd be happy to provide a patch for this, but I'd prefer universal interface support where possible. Therefore, this ticket, in my mind, is behind http://dev.clojure.org/jira/browse/CLJ-803 etc.
Hide
Brandon Bloom added a comment -

Predicates for core types are also very useful for portability to CLJS.

Show
Brandon Bloom added a comment - Predicates for core types are also very useful for portability to CLJS.
Hide
Alex Fowler added a comment - - edited

Also, obviously I missed the (boolean? x) predicate in the original post. Did not even guess it is absent too until I occasionally got into it today. Currently the most clean way we have is to do (or (true? x) (false? x)). Needles to say, it looks weird next to the present (integer? x) or (float? x).

Show
Alex Fowler added a comment - - edited Also, obviously I missed the (boolean? x) predicate in the original post. Did not even guess it is absent too until I occasionally got into it today. Currently the most clean way we have is to do (or (true? x) (false? x)). Needles to say, it looks weird next to the present (integer? x) or (float? x).
Hide
Alex Fowler added a comment - - edited

Yes, they do, and sometimes the code has many checks like (instance? clojure.lang.Atom x). Ok, you can write a little function (atom? x) but it has either to be written in all relevant namespaces or required/referred there from some extra namespace. All this is just a burden. For example, we have predicates like (var? x) or (future? x) which too map to Java classes, but having them abbreviated often makes possible to write a cleaner code.

I feel the first group to be especially significant for it being about core Clojure concepts like atom and ref. Having to fall to manual Java classes check to work with them feels inorganic. Of course we can, but why then do we have (var? x), (fn? x) and other? Imagine, for example:

(cond
(var? x) (...)
(fn? x) (...)
(instance? clojure.lang.Atom x) (...)
(or (instance? clojure.lang.Named x) (instance? clojure.lang.LazySeq x)) (...))

vs

(cond
(var? x) (...)
(fn? x) (...)
(atom? x) (...)
(or (named? x) (lazy-seq? x)) (...))

The second group is too, essential since these concepts are fundamental for the platform (but you're right with the (exception? x) one).

Show
Alex Fowler added a comment - - edited Yes, they do, and sometimes the code has many checks like (instance? clojure.lang.Atom x). Ok, you can write a little function (atom? x) but it has either to be written in all relevant namespaces or required/referred there from some extra namespace. All this is just a burden. For example, we have predicates like (var? x) or (future? x) which too map to Java classes, but having them abbreviated often makes possible to write a cleaner code. I feel the first group to be especially significant for it being about core Clojure concepts like atom and ref. Having to fall to manual Java classes check to work with them feels inorganic. Of course we can, but why then do we have (var? x), (fn? x) and other? Imagine, for example: (cond (var? x) (...) (fn? x) (...) (instance? clojure.lang.Atom x) (...) (or (instance? clojure.lang.Named x) (instance? clojure.lang.LazySeq x)) (...)) vs (cond (var? x) (...) (fn? x) (...) (atom? x) (...) (or (named? x) (lazy-seq? x)) (...)) The second group is too, essential since these concepts are fundamental for the platform (but you're right with the (exception? x) one).
Hide
Alex Miller added a comment -

In general many of the existing predicates map to interfaces. I'm guessing these would map to checks on the following types:

atom? = Atom (final class)
ref? = IRef (interface)
deref? = IDeref (interface)
named? = Named (interface, despite no I prefix)
map-entry? = IMapEntry (interface)
lazy-seq? = LazySeq (final class)

throwable? = Throwable
exception? = Exception, but this seems less useful as it feels like the right answer when you likely actually want throwable?
pattern? = java.util.regex.Pattern

Show
Alex Miller added a comment - In general many of the existing predicates map to interfaces. I'm guessing these would map to checks on the following types: atom? = Atom (final class) ref? = IRef (interface) deref? = IDeref (interface) named? = Named (interface, despite no I prefix) map-entry? = IMapEntry (interface) lazy-seq? = LazySeq (final class) throwable? = Throwable exception? = Exception, but this seems less useful as it feels like the right answer when you likely actually want throwable? pattern? = java.util.regex.Pattern

People

Vote (6)
Watch (1)

Dates

  • Created:
    Updated: