Hi Julien,
Good and interesting point.
Your summary is correct: STON, inheriting from JSON so to speak, only knowns
about integer and float numbers. All other Smalltalk numbers get converted,
which results in a loss of type and precision. That might not be a perfect
situation, but nobody complained so far.
If we would change it, efficiency has to be taken into account: speed/memory
efficiency as well as human typing efficiency/complexity. Compatibility,
especially between different Smalltalk and other object languages, is also an
aspect.
Apart from the current approach, the full STON approach could be, for example
for 1/3 and 1.5s2
Fraction { #numerator:1, #denominator:3 }
ScaledDecimal { #numerator:3, #denominator:2, #scale:2}
For some types, STON uses shorter notations, either using positional arguments
Point [ 1, 2 ]
Fraction [ 1, 3 ]
ScaledFraction [ 3, 2, 2 ]
Or a string argument, when there is a clear external representation
DateAndTime [ '2018-09-18T16:39:10.325129+02:00' ]
Fraction [ '1/3' ]
ScaledFraction [ '3/2s2' ]
Of course, we could also extend the basic number parser and allow the native
(stored) notation
1/3
3/2s2
Note how that last one should use the more exact #storeOn: notation, not the
#printOn:
I'll have to think about this a bit more, as I can really not choose right now.
Sven
> On 18 Sep 2018, at 10:34, Julien <[email protected]> wrote:
>
> Hello,
>
> I realised that in the current implementation, when a number is serialised by
> STON it is either as an integer literal or as a float literal.
>
> There is a risk to loose precision, especially if what you serialise is a
> ScaledDecimal or a fraction.
>
> I propose a simple change to fix this:
>
> 1. Add STONWriter>>#isInJsonMode method which returns true if the STONWriter
> wants to write JSON
>
> 2. Add:
>
> Fraction>>#stonOn: stonWriter
> stonWriter isInJsonMode
> ifTrue: [ ^ super stonOn: stonWriter ].
>
> stonWriter writeObject: self streamMap: [ :dictionary |
> dictionary at: #numerator put: numerator.
> dictionary at: #denominator put: denominator ]
>
> 3. Add:
>
> ScaledDecimal>>#stonOn: stonWriter
> stonWriter isInJsonMode
> ifTrue: [ ^ super stonOn: stonWriter ].
>
> stonWriter writeObject: self streamMap: [ :dictionary |
> dictionary at: #numerator put: numerator.
> dictionary at: #denominator put: denominator.
> dictionary at: #scale put: scale ]
>
>
> This change has a main drawback, storing fractions and scaled decimal will
> result in a huge overhead.
>
> Maybe for ScaledDecimal we can use Pharo’s literal (e.g. 1.12s2).
>
> For fractions I don’t know what literal could be used?
>
> Or maybe the overhead is fine?
>
> Cheers,
>
> Julien
>
> ---
> Julien Delplanque
> Doctorant à l’Université de Lille
> http://juliendelplanque.be/phd.html
> Equipe Rmod, Inria
> Bâtiment B 40, Avenue Halley 59650 Villeneuve d'Ascq
> Numéro de téléphone: +333 59 35 86 40
>