-
Notifications
You must be signed in to change notification settings - Fork 25
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
Allow preservation of precision for JSON numbers in json_read #130
Comments
That is not a hook, but some extra functionality scoped by an option. I can live with that. Go ahead. Oh, and please add some documentation :) |
Yikes. Since you doubled the performance by moving json_read_number to C, we may have a problem. Everything is fine up until we use PL_chars_to_term to convert the string buffer into a number. Since this leads us quite deep into the parser, we have a couple of options:
Option 1 seems pretty hacky. Option 2 seems a bit extreme. Is there another option I might have missed? |
I think (2) is a bit too far stretched. At some point we may support decimals and provide an option to read_term to read x.y as decimal which could then end up as an option to PL_chars_to_term(). (1) is probably feasible. I'd add a boolean extra argument to The math is a bit of a problem. There is no foreign API for it. Not really sure I want this. I'd first call Prolog and to a performance test. Not sure how bad it will be. If to bad we need a plan B. |
You mean just call is/2 directly from C in a new frame? That's what I was thinking of as first attempt, but it seemed pretty rough. Performance is really not my concern (at least not at this stage) - I just want it to be correct :) If JSON only supports decimals that makes it pretty easy. Even more so if I'm allowed to just have a boolean argument rather than having to parse options. I'll put together a rough version that works, then you can direct where to apply the polish later |
Its internal, so need for an option list. If you follow the option encoding scheme of the JSON library it will be a simple direct lookup to get this boolean. I'd add a predicate json:mk_rational(+Int, +DigitsOfterDot, -Rational) and call that using PL_call_predicate(). Do not forget to create a foreign frame or you will run out of stack! If this proves too slow we can always add an additional API. Possibly you can bypass the general rule for numbers that fit easily in |
After issue #128, I realised that there's a problem going the other way as well. When we receive a value that we know is a number, we use number_codes/2 to turn it into a float. I would like to instead either allow a hook that I can use to create exact representations of the values as rdiv/2 terms, or provide an option to json_read/3 so that json_read_number/4 (which will become json_read_number/5, I guess) can create an rdiv/2 term for the input.
For example, if we receive a term like
{"foo": 123456789012345678901234567890}
this already turns up (for me, anyway) as
_{foo: 123456789012345678901234567890}
and not
_{foo: 1.2345678901234568e+29}
.However, a term like
{"foo": 0.123456789012345678901234567890}
could be preserved as
_{foo: 12345678901234567890123456789 rdiv 100000000000000000000000000000}
but instead I end up with
_{foo: 0.12345678901234568}
This would require the SWI installation to have GMP support (obviously) and to pass an option to json_read/3 to indicate that we should use rationals instead of floats for representing non-integer numbers.
In short:
Hopefully I've done a better job of explaining my proposal this time!
The text was updated successfully, but these errors were encountered: