This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (2)
- # aws (2)
- # babashka (1)
- # beginners (87)
- # boot (1)
- # calva (42)
- # clj-kondo (18)
- # cljdoc (5)
- # cljsjs (1)
- # cljsrn (1)
- # clojars (16)
- # clojure (222)
- # clojure-dev (30)
- # clojure-europe (17)
- # clojure-gamedev (2)
- # clojure-hungary (10)
- # clojure-italy (6)
- # clojure-nl (21)
- # clojure-spec (9)
- # clojure-uk (111)
- # clojuredesign-podcast (1)
- # clojurescript (99)
- # code-reviews (1)
- # conjure (18)
- # crux (26)
- # cursive (11)
- # datomic (22)
- # emacs (1)
- # events (3)
- # figwheel-main (3)
- # fulcro (14)
- # graalvm (41)
- # graphql (16)
- # helix (12)
- # juxt (1)
- # kaocha (56)
- # keechma (1)
- # meander (77)
- # observability (1)
- # off-topic (29)
- # pathom (3)
- # re-frame (4)
- # reagent (3)
- # reitit (1)
- # remote-jobs (3)
- # reveal (9)
- # shadow-cljs (45)
- # spacemacs (43)
- # sql (28)
- # tools-deps (14)
- # vim (1)
- # yada (1)
Does it seem sensible to anyone that this range
(range 0 (+ 1 (/ 9)) (/ 9)) has 11 elements in cljs (I'm not sure why), but if you convert it to a vector, it has 10?
It's really really weird to do things like have a range with 11 elements, but if you call butlast on it, it suddenly has 9.
I mean I assume this all has to do with numeric precision issues somehow but I have to imagine this is a bug.
I don't have a clue but my guess would be thats because clojurescript doesn't have true ratios so
1/9 is just a float as opposed to clojure
Yes, certainly. But I still think the behavior is wrong with regard to length and conversions.
It's weird to print it out and get a value that doesn't exist at all if you convert it to a vec.
probably just a bug in the
range impl. count is doing math instead of doing actual seq stuff.
the issue is just that
range only should take ints but your code will produce floating point (in ClojureScript)
@pmooser I'm also not totally sure what you are trying to accomplish since in Clojure that would produce rationals
so trying to determine if you're just doing something fundamentally that's not going to work that involves rationals
and expecting some kind of behavior - but I don't see what since it couldn't possible align with Clojure
@dnolen It's just math, that's what I'm trying to accomplish. If range should take only ints, I would love it if that fact was mentioned in the doc string.
I'll make sure to avoid using range for anything non-integral in the future, but I checked the doc string and found no mention of that limitation.
When I'm doing something with math or lots of floating point, I don't tend to share the exact same code between clojure and cljs due to their fundamental differences in underlying numeric types anyway. What I pasted here was a simplified expression that had the same behavior I was curious about in cljs.
I understand that you can't take the time to explain it, but I'm sort of still interested in why this occurs. It's not like an issue with float precision ... the final value is obviously way outside the range.
we could add docstrings all over the place about this but it wouldn't be that productive in my opinion
unless of course you saying the above should work w/ specific floating point values and you want some kind of defined behavior
I respect your opinion a lot. I don't think it's accurate to say that I'm asking for doc strings everywhere. I'm asking that things that result in crazy behavior be discoverable as "unsupported" or "undefined" without simply finding that the code doesn't work.
So what I don't understand is what you think is weird about what I'm doing or why it's unclear what it ought to do -
I understand maybe that's not supported with floats, but I'm saying that the expectation I have is simply stated.
You pasted it into a clojure repl? From my standpoint it works fine with clojure, except you get a promotion to 1N at the end of the interval.
But that's all wrapped up in what clojure does (which appears to be what I would expect), given its numeric tower.
(0.0 0.11111111 0.22222222 0.33333334 0.44444445 0.5555556 0.6666667 0.7777778 0.8888889 1.0)
That would be ideal, down to whatever differences are caused by JS' numeric precision.
What I was confused by is that range has the wrong number of items, and if you convert it to a vec, the last (incorrect) item disappears, and if you call butlast on it, you get a range that is 2 shorter (instead of merely one). It's a bit difficult to explain because the problem sort of vanishes if you start to manipulate the range in certain ways, so it's a bit challenging at the REPL to try to come up with great pastable examples.
In my cljs repl, that range has an additional item at the end,
1.1111111111111112 , meaning there are 11 items total, with the last one being obviously far past 'end'.
but it would have been clearer if you had said "I don't care about numeric tower details"
really the bug doesn't have anything do w/ vector though, far as I can tell the range should have only 10 elements not 11
Sure - that's just additional information (the vector part). I was just surprised that given that the range has the wrong size, that it corrects itself when you do certain things.
In any case, thank you very much for taking the time to understand this, and I'll try to make sure I am as clear as possible in the future.
range problem is probably impossible to fix while preserving perf in all cases. In Clojure, the result of
range is not
countable? which is, given the example above, probably the right answer.
We had copied over some aspects of
LongRange when adding
Maybe more of
LongRange would help avoid some of the floating point pitfalls
The discussion above mentions "Clojure's numeric tower" a few times. What is that? I've never heard about the concept before, and I can't find anything that would describe it.
Here is an example how ClojureScript's
range is hokey compared to Clojure's which uses a sane integer math only when possible:
(let [c (range 0 1 0.1)] [(nth c 6) (nth (vec c) 6)])
cljs.user=> (range 0 1 0.1) (0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0.9999999999999999) cljs.user=> (nth *1 6) 0.6000000000000001