This feature is actually part of ReScript 11 since about half a year now. It is also the new default going forward. As the article mentions, you will still be able to use auto-currying in ReScript 11, but uncurried is a better fit for new developers with mainly JS/TS experience.
Please try out ReScript 11 in your codebases and help us with feedback, that would be really great!
Is the add(5, _) (or add(_, 5)) syntax discouraged? It enables some patterns that ... doesn’t, so maybe it’s worth mentioning as yet another tool for point-free programming?
Ok, so to be clear, the _ syntax got a bit nerfed. If you want to partially apply everything but one parameter, it works the same. But if there are multiple parameters, you need to use the spread syntax now.
So while this works in both curried and uncurried mode:
let add = (a, b) => a + b
let addFive = add(5, _)
this only works in curried mode
let sum = (a, b, c) => a + b + c
let sumWith5 = sum(5, _)
let _ = sumWith5(1, 2)
and this only uncurried
let sum = (a, b, c) => a + b + c
let sumWith5 = sum(5, ...)
let _ = sumWith5(1, 2)
It was always the case that _ can only be used once.
Or rather, the implementation was never intended for multiple _ and replaces each one with the same value.
I just want to say the syntax ya’ll have chosen represents currying so perfectly. Looking forward to 11, I know I’ve been burned a couple times with the let _ = forgotSecondArg(x)
Overal I like currying but I did experience unexpected behavior several times while writing bindings without disabling it.
I have mixed fillings about uncurried mode but on other hand partial application is still possible and annotation is more explicit… and final unit was sometimes weird.
I’m happy to give the new mode a try
I played a bit with it. I was afraid it would break a typical Rescript application, but it seems it won’t.
If functions are not curried by default I wonder if these are still going to work:
[1, 2, 3]->Js.Array2.map(x => x + 1)
But fortunately, it works, so thankfully the biggest Rescript feature is preserved
To be honest, after depreciating pipe operators other than -> I always feel fearful about changes that may affect the remaining piping capabilities that in my opinion are essential to Rescript appeal. Especially because many modules are not rewritten to “data first” and it’s more practical to use Js.Array2 then Js.Array, but in many situations, it requires additional “boilerplate” with the underscore (ie. Some("test")->(Js.Option.map(x => x ++ "2", _))).
Having these underscore everywhere would be a nightmare.
If defined like this:
let p = Js.Array2.map(_, x => x + 1)
let res2 = [1, 2, 3]->p
Is kinda of fine, but I wonder how it works, that for pipes it’s somehow curried while for partially executed functions it doesn’t?
As the uncurried mode side effect, passing a function as a callback is no longer possible.
This doesn’t work (with message: This function is a curried function where an uncurried function is expected):
This is a specific of built-in modules, which will probably be fixed in later versions (v11.x or v12).
As a work around I suggest you to use rescript-core instead of the Js/Belt modules.