Already carried js functions


#1

I am trying to make definitions for already carried js functions. So outputted js will be like

closestIndexTo(dateArray)(date)

Trying to make something like that

[@bs.module "date-fns/fp/closestIndexTo"] 
external closestIndexTo: (array(date), date) => int = "default";

But it is always outputting me carried variants :((


#2

To explicitly tell BuckleScript that the JavaScript function is already curried, you can use the explicit uncurried syntax: https://bucklescript.github.io/docs/en/function#solution-guaranteed-uncurrying

E.g.

[@bs.module "date-fns/fp/closestIndexTo"] 
external closestIndexTo: (. array(date)) => (. date => int) = "default";

#3

I will add that if you’d like the binding to be curried on the Reason side too (to mimic the original), you could wrap the function from @yawaramin 's example in a small curry2 helper:

[@bs.module "date-fns/fp/closestIndexTo"]
external closestIndexToUncurried: (. array(date)) => (. date) => int = "default";

/* Calling the uncurried binding requires a bit of an awkward syntax: */
let result1 = closestIndexToUncurried(. [|date1, date2|])(. date3);

/* Converts uncurried function of two arguments to a curried function */
type uncurried2('a, 'b, 'c) = (. 'a) => (. 'b) => 'c;
type curried2('a, 'b, 'c) = ('a, 'b) => 'c;
let curry2 = (uncurried2: uncurried2('a, 'b, 'c)): curried2('a, 'b, 'c) => {
  (a, b) => uncurried2(. a)(. b);
};

/* New curried closestIndexTo function */
let closestIndexTo = curry2(closestIndexToUncurried);

/* You can now use it as any other Reason function */
let partial1 = closestIndexTo([|date1, date2|]);
let result2 = partial1(date3);
let result3 = closestIndexTo([|date4, date5|], date6);

#4

Thanks, but actually it is doing literally the same as native bs carry definitions doing. I thought there will be a way to natively convert carried reason function into the carried js function.
But seems like there is no way :frowning:


#5

BuckleScript by default uncurries all functions in the output JavaScript, for performance reasons. Most of the time that’s exactly what you need. For the other times when you need to output actual curried JavaScript functions, you can use the uncurried syntax as I mentioned. It works almost the same way when you’re defining a Reason function:

let add = (. x) => (. y) => x + y;

This outputs JavaScript:

function add(x) {
  return (function (y) {
      return x + y | 0;
    });
}

I know it’s a bit confusing to use uncurried syntax to get curried functions but the idea is that if you explicitly uncurry the functions separately, then BuckleScript won’t combine them into a single uncurried function like it normally would.