Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ryuheechul
Last active September 4, 2018 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryuheechul/573ea3c203d8fb736ed82480cb8dafbc to your computer and use it in GitHub Desktop.
Save ryuheechul/573ea3c203d8fb736ed82480cb8dafbc to your computer and use it in GitHub Desktop.
Attempts to make a reason function work in JS
[@bs.deriving jsConverter]
type args = {
key1: option(string),
key2: option(string),
key3: option(string),
};
let concat = ({key1, key2, key3}) =>
switch (key1, key2, key3) {
| (Some(k1), Some(k2), Some(k3)) => k1 ++ ", " ++ k2 ++ ", " ++ k3
| _ => "Something is None"
};
let concatFromJs = [%raw {|
({key1, key2, key3}) => {
const argArr = argsFromJs({key1, key2, key3})
return concat(argArr)
/* argsFromJs is generated by jsConverter */
}
|}];
/* test */
Js.log(
"call from reason: " ++
concat(
{key1: Some("value1"), key2: Some("value2"), key3: None}
)
);
Js.log(
"call from reason: " ++
concat(
{key1: Some("value1"), key2: Some("value2"), key3: Some("value3")}
)
);
[%raw {|
// optional check is fine with None
console.log('call from js:', concatFromJs({key1: "value1", key2: "value2"}))
|}];
[%raw {|
// optional check is not fine with Some
console.log('call from js:', concatFromJs({key1: "value1", key2: "value2", key3: "value3"}))
|}];
/* result are below
"call from reason: Something is None"
"call from reason: value1, value2, value3"
"call from js:" "Something is None"
"call from js:" "v, v, v" // argsFromJs is not handling option(string) from javascript correctly
*/
// so it makes really difficult to expose a function to javascript side that accepts objects possibly contains optional values
// exposing functions take js object with optional key
[%%raw "var john = {name: 'john', job: 'awesome job'}"];
type person = Js.t({
.
name: string,
age: option(int),
job: string
});
[@bs.val] external john : person = "john";
let p: person = [%bs.obj {
name: "person name",
job: "person job",
age: None
}];
let getName = (a: person) => a##name
let getAge = (a: person) => switch (a##age) {
| None => 0
| Some(n) => n
}
let pn = p##name
let name = john->getName;
let age = john->getAge;
Js.log(name);
Js.log(age);

I wanted to make an npm module via ReasonML

  • a function need to accept objects
  • but couldn't find a way to convert an JS Object to a Reason Record (holds optional value)
// I wanted to have an npm module function like below
reasonFnExposedToJs({key1: 'blah', key2: undefined})

// and works fine with Reason side but generated argsFromJs looks like below
function argsFromJs(param) {
  return /* record */[
          /* key1 */param.key1,
          /* key2 */param.key2,
          /* key3 */param.key3
        ];
}
// which doesn't map possible optional values

// so end up printing only first character of string since option is implemented as [something]
@ryuheechul
Copy link
Author

I made this gist to file an issue to Reason.
Now I tried the same code with Reason online editor, and it works fine, so I think it's fixed now with new version.

@ryuheechul
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment