ClojureScript

int? predicates inconsistent with Clojure

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Patch:
    Code

Description

This ClojureScript change
https://github.com/clojure/clojurescript/commit/bcf60ce194e5292fbc5c4b2d89dfc5a7b886b94c
tracked this Clojure change
https://github.com/clojure/clojure/commit/20f67081b7654e44e960defb1e4e491c3a0c2c8b

A consequence is that int? is satisfied by goog.math.Integer which is not fixed-precision.
Also, it creates a situation where it is possible to have values that satisfy int? but don't satisfy integer? or number?. (Note that this also affects things like pos-int?.)

I'd propose two alternative approaches to fix this that we can debate:

Alternative A: Simply remove the goog.math items from int? and friends.

Alternative B: Have goog.math.Long values satisfy number?, integer?, and int? and have goog.math.Integer values satisfy number? and integer?.

In either case, the docstrings should be updated.

I'll attached two concrete patches for consideration / debate.

Activity

Hide
Francis Avila added a comment - - edited

What should be the goal for the various numeric predicates in CLJS?

Is the goal to align with CLJ's meaning of these predicates? If so then:
number? true for typeof-number or goog.math.Integer or goog.math.Long
integer? true for goog.math.isInt/Number.isInteger or goog.math.Integer or goog.math.Long
int? true for goog.math.isInt/Number.isInteger or goog.math.Long

Is the goal to align with some notion of platform-primitiveness? If so then:
number? true for typeof-number or goog.math.Integer or goog.math.Long
integer? true for goog.math.isInt/Number.isInteger or goog.math.Integer or goog.math.Long
int? true for goog.math.isInt only

Is the goal to be a can-I-do-arithmetic-with-this type check? If so then:
number? true for typeof-number only
integer? true for goog.math.isInt (or maybe even Number.isSafeInteger)
int? same as integer?

In Java/CLJ these three goals are much more aligned with one another. Any number-as-identifier can also be used for clj arithmetic (so the widest check, number?, can also be used for arithmetic checking), and int? corresponds exactly to the host's most-primitive integer value-types (vs object-type).

CLJS lacks a number tower so it's more interesting.
Right now in CLJS number? appears to be designed as a predicate to test for whether arithmetic is possible, so it only allows js type-of===number. integer? is also an arithmetic check, but wants a non-fractional number (interestingly, still allowing unsafe integers, i.e. outside Number.MAX_SAFE_INTEGER, where normal integer arithmetic doesn't work--perhaps it should only allow safe integers). int? doesn't care about arithmetic, but it's still useful for seeing if a value could be a numeric identifier (e.g. a record id received via transit); but that's expressly not what CLJ's int? cares about.

Show
Francis Avila added a comment - - edited What should be the goal for the various numeric predicates in CLJS? Is the goal to align with CLJ's meaning of these predicates? If so then: number? true for typeof-number or goog.math.Integer or goog.math.Long integer? true for goog.math.isInt/Number.isInteger or goog.math.Integer or goog.math.Long int? true for goog.math.isInt/Number.isInteger or goog.math.Long Is the goal to align with some notion of platform-primitiveness? If so then: number? true for typeof-number or goog.math.Integer or goog.math.Long integer? true for goog.math.isInt/Number.isInteger or goog.math.Integer or goog.math.Long int? true for goog.math.isInt only Is the goal to be a can-I-do-arithmetic-with-this type check? If so then: number? true for typeof-number only integer? true for goog.math.isInt (or maybe even Number.isSafeInteger) int? same as integer? In Java/CLJ these three goals are much more aligned with one another. Any number-as-identifier can also be used for clj arithmetic (so the widest check, number?, can also be used for arithmetic checking), and int? corresponds exactly to the host's most-primitive integer value-types (vs object-type). CLJS lacks a number tower so it's more interesting. Right now in CLJS number? appears to be designed as a predicate to test for whether arithmetic is possible, so it only allows js type-of===number. integer? is also an arithmetic check, but wants a non-fractional number (interestingly, still allowing unsafe integers, i.e. outside Number.MAX_SAFE_INTEGER, where normal integer arithmetic doesn't work--perhaps it should only allow safe integers). int? doesn't care about arithmetic, but it's still useful for seeing if a value could be a numeric identifier (e.g. a record id received via transit); but that's expressly not what CLJ's int? cares about.
Hide
Mike Fikes added a comment - - edited

The attached A and B patches explore the two approaches.

Patch A could probably be applied as it exists now.

Patch B on the other hand seems to have lots of consequences related to whether something that satisfies number? can participate in arithmetic or be used in other places where numbers are currently used. I suspect we could make all of this work but we'd be giving up a lot of perf.

As one concrete example: Is this a valid program, and should it return true?

(zero? goog.math.Integer/ZERO)
Show
Mike Fikes added a comment - - edited The attached A and B patches explore the two approaches. Patch A could probably be applied as it exists now. Patch B on the other hand seems to have lots of consequences related to whether something that satisfies number? can participate in arithmetic or be used in other places where numbers are currently used. I suspect we could make all of this work but we'd be giving up a lot of perf. As one concrete example: Is this a valid program, and should it return true?
(zero? goog.math.Integer/ZERO)

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: