Fable icon indicating copy to clipboard operation
Fable copied to clipboard

System.Decimal.TryParse behaves differently in .NET and Fable

Open mattgallagher92 opened this issue 2 years ago • 8 comments

Description

In some locales, strings representing decimal numbers sometimes have thousands separators. For example, the number 4242 might sometimes be written as 4,242 in the UK. This is parsed correctly in F# interactive, but fails to parse in Fable.

This poses some challenges when trying to share code between client and server in SAFE apps.

Repro code

Evaluating System.Decimal.TryParse "4,242" in FSI gives the value it: bool * decimal = (true, 4242M).

The Fable REPL equivalent demonstrates the error.

Expected and actual results

Expected: (true, 4242M)

Actual: (false, 0M)

Related information

  • Fable version: 4.1.3
  • Operating system: REPL in Brave browser on Ubuntu 22.04

mattgallagher92 avatar Jun 15 '23 15:06 mattgallagher92

Obviously a quick fix in this case, would be to strip commas, but that has implications for other locales (for example Germany) where commas are used as the decimal separator and full stops are used as thousand separators.

For example, the number represented in the UK as 4,242.42 could be represented in Germany as 4.242,42

mattgallagher92 avatar Jun 15 '23 15:06 mattgallagher92

There may well be additional cases where parsing behaves differently; I haven't done an exhaustive check.

mattgallagher92 avatar Jun 15 '23 15:06 mattgallagher92

This one is tricky because Fable, tries to avoid supporting globalisation in general because it is difficult to implements as their are a lot of variant.

The code responsible for Decimal.tryParse is located at

https://github.com/fable-compiler/Fable/blob/ac4d44997f69d5b1b7109730ccb45e354a4ec368/src/fable-library/Decimal.ts#L124C8-L131

It is using a custom big.js implementation.

I don't see an easy way to fix this issue as it would probably requires to implement different rules based on the detected country of the user. I believe this is done nowhere else in Fable.

MangelMaxime avatar Jun 15 '23 16:06 MangelMaxime

@mattgallagher92 If I'm not mistaken, currently Fable only supports the InvariantCulture, similar to what JavaScript number parsing supports.

ncave avatar Jun 15 '23 16:06 ncave

Thanks both. I guess as a workaround then, I could remove commas if I know that they are being used as thousands separators. Let me know if you have a better suggestion.

mattgallagher92 avatar Jun 15 '23 16:06 mattgallagher92

Another suggestion is to look in the JavaScript ecosystem if there is a library supporting the features you need.

You can use it just to parse the user input and then pass it to Fable decimals if precision is required or for network serialisation.

MangelMaxime avatar Jun 15 '23 20:06 MangelMaxime

Thanks Maxime, I'll investigate.

Quick question before we close the issue: is this difference documented anywhere? I didn't see it on https://fable.io/docs/dotnet/compatibility.html or https://fable.io/docs/dotnet/numbers.html.

If it's not documented elsewhere, would you like me to raise a PR to add a note to one of those pages?

mattgallagher92 avatar Jun 20 '23 14:06 mattgallagher92

I don't think it is explicitly mentioned on the documentation.

I know that if you try to pass the Globalization arguments then Fable log a warning.

MangelMaxime avatar Jun 21 '23 08:06 MangelMaxime