How to prepare for uncurried in Rescript 11

I want to prepare my repos for the upcomming Rescript v11; which I’ve somewhere (but I can’t find now in the #announcements) will default to uncurried functions.

I use the curried-by-default idiom very often. So I want to prepare. Is the definite blog post or documentation about this change and how to configure you project to opt-in/out?

4 Likes

The uncurried mode is indeed going to be the default one (it’s already from v11 beta 3 or 4).
But you don’t need to do any preparations, since it’s possible to set “uncurried”: false in your bsconfig to have it working as it is now.
Also, setting it to false and then gradually adding @@uncurried on top of the files, in my opinion, is the best way of migrating projects to the uncurried by default mode.

3 Likes

Hi @DZakh,

Thanks for your response. Do you know about a blog post or document page where the options are enumerate? It’s also possible to have the default and change it per module or per-function (i.e something like @curry or @@curry)?

2 Likes

There will be a dedicated blog post about it to also explain the impact on the ecosystem if we decide to make this the default. Sorry for the delay.

Right now is a typical summer hole, so I hope we’ll be able to write it up somewhere this month.

does this mean that now the uncurry syntax (. ) is now the curry syntax in v11?

Great! Looking forward for this post. I know @zth has written about it twitter, but I can’t find those now, though. So having a post/doc page for this would be really nice.

I believe there is no explicit curry syntax IIRC. \cc @cristianoc

We have some explicit partial application syntax though:

let add = (a, b) => a + b

let add2 = add(2, ...)

add2(2)->Js.log

Playground link

6 Likes

thanks

Do you know if rescript-react also has to be in the latest alpha to support rescript v11?

Yes, you need 0.12

1 Like

So I wanted to update my libraries to work in Rescript 11 as well as in Rescript 10; but the formatter is hindering my efforts.

For instance, this code (in 10):

  @doc("Run each function in turn until one resolves to an Error, or all resolve to Ok.")
  let bail: array<unit => t<'a, 'e>> => t<array<'a>, 'e> = _bail

...

  let untilOk: array<unit => t<'a, 'e>> => t<option<'a>, 'e> = async actions => {
    switch await actions->Array.map((a, _) => a()->flip)->bail {
    | Error(r) => Ok(Some(r))
    | Ok([]) => Ok(None)
    | Ok(errors) => Error(errors->Array.getUnsafe(0))
    }
  }

Requires to change the expression actions->Array.map((a, _) => a()->flip)->bail to actions->Array.map(a => _ => a()->flip)->bail for it to type-check in Rescript 11; but the formatter of Rescript 10 will reverse it back.

On the other hand resolve(. val) is changed by the formatter of Rescript 11 to just resolve(val) which won’t work on Rescript 10.

The only solution is to either no use the formatter; or maintain a separate branch.

Another experience report

In some projects, I have had to use "uncurried": false only to satisfy the dependencies; and then use @@uncurried in all of the main project modules.

1 Like

Like @ryyppy there will be a thorough blog post about this soon, and of course documentation as well. However, before that, we’ll soon establish an FAQ where we can gather information and answers to common questions that you’re likely to hit. Hoping to get that ball rolling very soon.

3 Likes

Hi @zth,

Thanks a lot!

I’m just using this post to report some of issues I’m finding. It might be helpful to others in the meantime.

2 Likes

Another issue I have found.

I have some libraries which are uncurried-ready; but other which are not (e.g rescript-webapi). This forces the main project to set "uncurried": false, because otherwise rescript-webapi fails to compile.

But the uncurried libraries need to have an explicit @@uncurried in all modules. Having "uncurried": true in their bsconfig.json is not enough. The compilation of the main project fails (after a clean checkout) inside the uncurried-ready libraries.

4 Likes

I’m doing it this way for my libs :+1:

Is there a corresponding @@curried to explicitly states that the module is curried?

@dsiu

AFAIK, there’s @@uncurried.swap. So you can do:

@@uncurried
@@uncuried.swap

to make a module curried.

1 Like

Note that it works a little bit different from the legacy mode and mostly added for testing.

Thanks, it works. I understand that @@uncurried and @@uncurried.swap might be removed in the future.

let f = (a, b, c) => {
  a + b + c
}

// in uncurried mode, spread operator can be used to curry an uncurried function f
let g = f(1, 2, ...)

@@uncurried
@@uncurried.swap
// in curried mode, p needs . to specify the function is curried
let p = (. a, b, c) => {
  a - b - c
}

let q = p(1)
let q' = q(2)

Playgound Link

1 Like