-
-
Notifications
You must be signed in to change notification settings - Fork 52
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
Figure out to deal with pipe first vs pipe last libraries #731
Comments
We discussed offline that maybe we can design the API in a way that is friendly for both pipe first and pipe last. We can do so by putting the As an example, instead of the current implementation of melange/jscomp/runtime/js_string.ml Lines 196 to 197 in 65d1702
Or the one in melange/jscomp/runtime/js_string2.ml Lines 196 to 197 in 65d1702
We could do something like: external includes : t -> substring:t -> bool = "includes" [@@mel.send] That way, users of the library can decide how to use it: let a = "Hello world" |> Js.String.includes ~substring:"Hello"
let b = "Hello world" |. Js.String.includes ~substring:"Hello" |
One thing to consider about pipe last is that the generated code will be less performant. Consider this example: type keycloak
external keycloak : keycloak = "default" [@@mel.module "keycloak-js"]
type initParam
external makeInitParam : onLoad:string -> unit -> initParam = "" [@@mel.obj]
type init
external init : keycloak -> param:initParam -> init = "init" [@@mel.send]
let one = keycloak |> init ~param:(makeInitParam ~onLoad:"login" ())
let two = keycloak |. init ~param:(makeInitParam ~onLoad:"login" ()) And the generated code for // Generated by Melange
import KeycloakJs from "keycloak-js";
var arg = {
onLoad: "login"
};
var one = (function (param) {
return param.init(arg);
})(KeycloakJs);
var two = KeycloakJs.init({
onLoad: "login"
});
export {
one ,
two ,
}
/* one Not a pure module */ |
Hmmm the performance example is a lack of optimization. This inlining could potentially change the evaluation order, but for most cases(like this one) you can guarantee that this is not the case. |
Based on discussions back then there was some reason the AST makes that optimization hard for |
@jchavarri the issue with the performance example is that it's mixing type keycloak
external keycloak : keycloak = "default" [@@mel.module "keycloak-js"]
type initParam
external makeInitParam : onLoad:string -> initParam = "" [@@mel.obj]
type init
external init : param:initParam -> init = "init" [@@mel.send.pipe: keycloak]
let one = keycloak |> init ~param:(makeInitParam ~onLoad:"login")
let two = keycloak |. init ~param:(makeInitParam ~onLoad:"login")
// Generated by Melange
import KeycloakJs from "keycloak-js";
var one = KeycloakJs.init({
onLoad: "login"
});
var two = KeycloakJs.init({
onLoad: "login"
});
export {
one ,
two ,
}
/* one Not a pure module */ |
I think this one has been fixed by the recent changes. |
Right now we have the unfortunate situation where pipe last and pipe first modules are all together under
Js
, e.g.Js.String
is pipe last andJs.String2
is pipe first. We could addJs.DataFirst
modules that allow you to use pipe first operators while the standardJs
modules support pipe last operator as they always have. In your program you can specify your preference for pipe first by addingopen Js.DataFirst;
to the top of a source file or-open Js.DataFirst
in dune file.This is analagous to StdLabels which allows you to easily swap out normal List functions with versions that use labeled arguments.
The text was updated successfully, but these errors were encountered: