-
Notifications
You must be signed in to change notification settings - Fork 324
V07 value impl #246
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
V07 value impl #246
Conversation
|
||
@Override | ||
public Value getOrNilValue(int index) { | ||
if (array.length < index && index >= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition seems to be backwards. I think it should be index < array.length
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ouch. fixed.
return ValueFactory.newIntegerValue(unpackLong()); | ||
} | ||
case FLOAT: | ||
return ValueFactory.newFloatValue(unpackDouble()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remembered why FloatHolder was necessary. When reading a float value as double, it will add some fractions. For example:
scala> 0.1341f.toDouble
res5: Double = 0.13410000503063202
If user wants to print this float value as String, 0.13410000503063202
will be shown. This is unexpected behavior for the user.
Another example: 0.1f
becomes 0.10000000149011612
string if we use double as 0.1f
s internal representation.
I'll fix this in another pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is OK to say say that it's a limitation because of internal representation of a Value because anyways it is impossible to preserve all information of floating point numbers using decimal string format.
A reason is this trade-off: First of all, Float.intBitsToFloat(0x3e09374c)
is equal to Double.longBitsToDouble(0x3fc126e980000000)
in MessagePack because MessagePack does not distinguish single-precision from double-precision in terms of type system. So, FloatValue#equals
method 1) should always use double
, or 2) should always cast to single-precision float if precision of the actual value fits in single-precision float like IntgerValue implementation. Same for FloatValue#hashCode()
. If we take 1), when floatValue.equals(other)
returns true, floatValue.toString().equals(other.toString())
may return false. If we take 2), deserialization of msgpack's float 64
format becomes slow.
If implement, options are:
a) create ImmutableFloatValueImpl as you mention
b) add boolean floatIsSinglePrecision
field. If this is true, toString()
and writeTo(Packer)
uses single-precision.
I think b) is better for Variable. Otherwise Variable#equals
method becomes more complicated. For ImmutableValue, a) or b).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed this topic with @frsyuki. MessagePack type system will not preserve the error range of float values since some msgpack implementation cannot have float values. So application developers needs to be careful so as not to write a code that depends on float precision. Even if the data is written in FLOAT32, Value interface will represent it in double precision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going this route means that if a single precision number is in the data stream and read into a value. Value.writeTo
will write a double to the MessagePacker. Should writeTo
reproduce the original msgpacked data or just something close to it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This discussion has started in MessagePack specification side:
msgpack/msgpack#200
If we can preserve original message-packed data in an efficient way, lossless writeTo
implementation would be useful, but the message type system does not require it.
…f integer overflow
…test Fix unit test errors
V07 value impl revision 2
@muga How about renaming these methods as follows?:
Then remove getXXX methods. |
How about this simply?
I think it's a possible idea to separate toJson from toString. However, because some values are not compatible with JSON (non-string keys of a map, ExtensionValue, floating point values, etc.), we would need another class like ValueToJsonPacker that converts Value to JSON so that the conversion behavior can be configurable using the constructor of the packer class. |
@frsyuki My concern on StringValue.toString is it always returns double quoted value in generating string messages with StringValue. |
Using double quoted string looks good for distinguishing StringValue "1" and FloatValue 1 when debugging. OK. I'll go with roundToXXX, getXXX and toString. toJSON should be implemented in another class as @frsyuki said. |
A problem is getting float value has no good name like roundToXXX. How about using If we use asXXX, we can simply say representing this value as XXX type. mmm. But asXXXValue is already used for converting Value types. So castAsXXX might be better. |
Merged. Will add test codes and further internal improvement in another PR. |
Why don't you use roundToXxx? I think that castAsXxx assumes that users understand the actual implementation the methods. If we assume that users don't have to know the actual implementation, I think castToXxx is confusing because I don't know whether it throws exceptions or not. For example, In my opinion, roundToFloat / roundToDouble is correct name because it actually can rounding. |
@xerial How about this radical idea?:
With this idea, you can achieve short names and consistent concept at the same time. |
@frsyuki
|
@frsyuki |
@xerial I think that Value.asAbcValue methods are also a kind of asXxx methods because it doesn't lose information, may throw exception, and Xxx is the returning class name. |
If having |
This pull request implements Value API.