-
-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Numbers don't match with specification. #106
Comments
I don't mind using i64 and u64 for integers, and something like i128/u128 for BigInt. However, there is certainly a problem using f64 for decimal and big decimal as it breaks precision, ordering and hashing. It would require a library like ordered float to wrap that. @evaporei opinions? |
I have the same opinion for integers. As for floating point, I'm ok with bringing ordered float back again into the codebase. |
Is there a reason for a separate u64 on top of i64? I suppose it's not an issue because clojure will read 2^64-1 as a BigInt. When converting from a u64 to a string it should probably add the N character at the end if it is over 2^32. I think this sort of issue is probably more painful than just having an i64 and having the user code have a try_into() (there would likely need an if/match to determine Int vs UInt anyway) I hadn't considered FP ordering and hashing. I'm not sure clojure handles arbitrary precision here either (cljs almost surely doesn't). |
Basically, I had an issue that the number was larger than i64::MAX. Why not just use all resources available and allow the Rust version to be compatible with larger numbers like i128? |
Actually, I would be happy with usize/isize to u64/i64, consistent results on all architectures. |
Have you experimented with a branch for this? |
I do not. I can start one though. I haven't thought about this in a little bit, but I think the TODOs and/or things to evaluate are
I don't know what to do about floating point numbers. I think the current implementation is very dangerous though. Certainly allowing silent c-style casting of f64 to f32 should probably be removed. I would think just using f64 everywhere (as suggested by the edn spec) would be easiest. Doing this also ensures we're conforming to the IEEE-754 spec (by inheriting from rust's std). I believe this is also what is ensured in both clj and cljs by the jvm/js Here's an example where we certainly do not conform (and have a fallible impl). Other edge cases would be rounding implementations, inf, -inf, and NaN
|
I do not oppose any of them, I just didn't understand number 4, what is FP? Maybe the casting could be done with option as well, so you could have a Result casting and an option casting, which seems more rusty like the checked operations |
There might have some work on end-derive crate |
Trying to make Double conform to IEEE-754 is quickly going to end up just reinventing td::f64 and ordered_float (external crate). Using only f64 everywhere also helps with equality rules and seems to be what edn expects anyway. End users can handle the type conversions themselves (it would probably a domain specific with edge cases out of scope of a parsing library). With number 2 on my list, we could add ArbitraryPrecision later down the road without breaking changes. Maybe there will be a nice crate or even a std impl at some point. I can't imagine an obvious use case to serialize arbitrary precision data like this, but it keeps the option available. |
Sounds like a solid plan. We did considered using ordered-float, but it was a heavy dependency at the time. Not sure how it looks now |
ordered-float is pretty small, at least with I think I'll bring in ordered-float and see if it can work nicely without default-features. Then introduce our own default-features with the first addition being a feature |
Right now the numbers are
https://github.com/edn-format/edn#integers
https://github.com/edn-format/edn#floating-point-numbers
According to the spec, integers should be i64 and floating points should be f64. I don't think we can de arbitrary precision with N or M without software implementations. I think perhaps things should be i64 and f64 in the normal case. With #105 maybe we can match against N to i128? I don't think we can practically match the N/M spec without pulling in dependencies, however the current isize/usize is certainly off-spec compared to the expected types, depending on the target architecture.
Changing this would be a breaking pub API change. Has there been any precedence? Perhaps a 0.18.0?
The text was updated successfully, but these errors were encountered: