Manipulating some maps returns some odd results in Fable when compared with F#.
I personally think its because Fable may miscompile OptimizedClosures.FSharpFunc<_,_,_>.Adapt
The test in question is described here.
The functions used in the test are implemented here
deepEqual is defined as Expecto.equalSequence when run with F# and as Assert.deepStrictEqual when run with JS.
In F# the test passes and the following gets printed:
m1: map [(1, "1"); (2, "2"); (3, "3")]
m2: map [(3, "3"); (4, "4"); (5, "5")]
r1: map [(3, "3")]
r2: map [(3, "3")]
In Fable the test fails and the following gets printed:
m1: map [(1, 1); (2, 2); (3, 3)]
m2: map [(3, 3); (4, 4); (5, 5)]
r1: map [(3, a2 => f(a1, a2))]
r2: map [(3, a2 => f(a1, a2))]
map [(3, a2 => f(a1, a2))] map [(3, a2 => f(a1, a2))]
1) Map.intersect returns same results independent of the order (commutative)
This change to Library/Library.fs makes it work:
module Map =
let mapValues2 f (x: Map<'Key, 'T1>) (y: Map<'Key, 'T2>) = Map <| seq {
- let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f
for KeyValue(k, vx) in x do
match Map.tryFind k y with
- | Some vy -> yield (k, f.Invoke (vx, vy))
+ | Some vy -> yield (k, f vx vy)
| None -> () }
Produces the following JS:
import { ofSeq, tryFind } from "fable-library/Map";
import { value } from "fable-library/Option";
import { delay, collect, singleton, empty } from "fable-library/Seq";
-import { compare, curry } from "fable-library/Util";
+import { compare } from "fable-library/Util";
export function mapValues2(f, x, y) {
return ofSeq(delay(function () {
- const f$$1 = f;
return collect(function (matchValue) {
const activePatternResult729 = matchValue;
const matchValue$$1 = tryFind(activePatternResult729[0], y);
if (matchValue$$1 == null) {
return empty();
} else {
const vy = value(matchValue$$1);
- return singleton([activePatternResult729[0], curry(2, f$$1)(activePatternResult729[1], vy)]);
+ return singleton([activePatternResult777[0], f(activePatternResult777[1], vy)]);
}
}, x);
}), {
Compare: compare
});
}
@inosik So that confirms that could be a bug in the way OptimizedClosures.FSharpFunc<_,_,_>.Adapt is compiled by Fable?
@jbotto94 Yes, it is a bug (or not implemented), I'll take a look. In the mean time, you can use System.Func<_,_,_>(f) instead.
Thank you both for the reports! Yes, the TODO comment here seems to indicate I wasn't very sure what I was doing when replacing that function 馃槄
Thanks to the JS diff kindly posted by @inosik I realized this was an issue with Fable uncurrying. With this commit your tests work now @jbotto94 :+1: (you can check here how to use Fable from source, but I will push a new fable-compiler release with the fix soon anyways).
@alfonsogarciacaro Thank you so much!
Most helpful comment
Thank you both for the reports! Yes, the TODO comment here seems to indicate I wasn't very sure what I was doing when replacing that function 馃槄
Thanks to the JS diff kindly posted by @inosik I realized this was an issue with Fable uncurrying. With this commit your tests work now @jbotto94 :+1: (you can check here how to use Fable from source, but I will push a new fable-compiler release with the fix soon anyways).