fable-compiler / Fable

F# to JavaScript, TypeScript, Python, Rust and Dart Compiler
http://fable.io/
MIT License
2.89k stars 295 forks source link

sorting a Resizearray differs from .NET #2506

Open goswinr opened 3 years ago

goswinr commented 3 years ago

I noticed that sorting a ResizeArray in Fable does not match .NET behaviour. Is this a known limitation (or a bug) ?

let a = [| "a"; "Z" |] |> Array.sort
printfn "%s" a.[0] // "Z" in fable and fsi

let r = ResizeArray(a)
r.Sort()
printfn "%s" r.[0] // "Z" in fable repl, "a" in fsi.exe

REPL: 3.2.6 Fable: 3.2.5

(I would actually argue that the .NET and F# behavior is confusing, but that's another discussion.)

inosik commented 3 years ago

I think this is a consequence of .NET trying to respect the systems language settings when it comes to strings. I can reproduce the behavior of FSI in the browser console with this:

const a = ['a', 'Z']

a.sort((a, b) => a.localeCompare(b))
// > Array [ "a", "Z" ]

a.sort()
// > Array [ "Z", "a" ]

On the other hand, the standard Array.sort function seems to use ordinal sorting, like JS and most other platforms and languages. The behavior you see in FSI can be reproduced with this C# snippet:

using System;
using System.Collections.Generic;
using System.Globalization;

var a = new List<string> { "a", "Z" };

// Same as a.Sort()
a.Sort(StringComparer.Create(new CultureInfo("de"), ignoreCase: false));
Console.WriteLine(a[0]); // a
Console.WriteLine(a[1]); // Z

// Same as [| "a"; "Z" |] |> Array.sort
a.Sort(StringComparer.Ordinal);
Console.WriteLine(a[0]); // Z
Console.WriteLine(a[1]); // a