Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @mel.unwrap with uncurry #1027

Closed
tatchi opened this issue Jan 10, 2024 · 5 comments
Closed

Support @mel.unwrap with uncurry #1027

tatchi opened this issue Jan 10, 2024 · 5 comments

Comments

@tatchi
Copy link
Contributor

tatchi commented Jan 10, 2024

I was trying to create bindings for the following Js code:

let navigate = useNavigate();

// Then later on in e.g an event handler:
navigate("/path") // or navigate(-1)

I tried the following reason code

[@mel.module "react-router-dom"]
external useNavigate:
  (unit, [@mel.unwrap] [ | `Str(string) | `Int(int)]) => unit =
  "useNavigate";

let navigate = useNavigate();

navigate(`Int(-1))

But it doesn't compile to what I need (related to #1022)

import * as ReactRouterDom from "react-router-dom";

function navigate(param) {
  ReactRouterDom.useNavigate(param.VAL);
}

ReactRouterDom.useNavigate(-1);

export {
  navigate ,
}

I thought I would use an uncurried version but it doesn't work with @mel.unwrap

[@mel.module "react-router-dom"]
external useNavigate:
  unit => (. ([@mel.unwrap] [ | `Str(string) | `Int(int)])) => unit =
  "useNavigate";

let navigate = useNavigate();
navigate(. `Str("hello"));

It gives the following alert:

Line 3, 16:
Alert: unused Unused attribute [@mel.unwrap]
This means such annotation is not annotated properly.
For example, some annotations are only meaningful in externals

The uncurried version without @mel.unwrap compiles to what I'd need (except that the argument is not unwrapped ofc)

[@mel.module "react-router-dom"]
external useNavigate: unit => (. [ | `Str(string) | `Int(int)]) => unit =
  "useNavigate";

let navigate = useNavigate();
navigate(. `Str("/path"));
import * as ReactRouterDom from "react-router-dom";

var navigate = ReactRouterDom.useNavigate();

navigate({
      NAME: "Str",
      VAL: "/path"
    });

export {
  navigate ,
}

Should we support @mel.unwrap with uncurry?

@anmonteiro
Copy link
Member

In the meantime you can try Js.undefined instead of unit if you really need the undefined argument.

@tatchi
Copy link
Contributor Author

tatchi commented Jan 10, 2024

Also note that in rescript 11, we can use unboxed with multiple constructors, so the following code compiles to what I need:

@unboxed
type stringOrInt = Str(string) | Int(int)

@module("react-router-dom")
external useNavigate: unit => stringOrInt => unit = "useNavigate"

let navigate = useNavigate()

navigate(Str("/path"))

Would supporting unboxed for multiple constructors be an option in melange?

@tatchi
Copy link
Contributor Author

tatchi commented Jan 10, 2024

In the meantime you can try Js.undefined instead of unit if you really need the undefined argument.

Thanks, I tried with

[@mel.module "react-router-dom"]
external useNavigate:
  (Js.undefined(unit), [@mel.unwrap] [ | `Str(string) | `Int(int)]) => unit =
  "useNavigate";

let navigate = useNavigate(Js.undefined);

navigate(`Int(-1));

But it stills doesn't compile to what I need:

import * as ReactRouterDom from "react-router-dom";

function navigate(param) {
  ReactRouterDom.useNavigate(undefined, param.VAL);
}

ReactRouterDom.useNavigate(undefined, -1);

export {
  navigate ,
}

Is it what you had in mind ?

@anmonteiro
Copy link
Member

This exposes a wider issue that we don't support these attributes inside uncurried externals, e.g.:

external x: (. ([@mel.as "hello"] _)) => unit = "asd";

@anmonteiro
Copy link
Member

fixed in #1140

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants