[@bs.deriving abstract] - Feedback


#1

I have been playing around a bit with the new [@bs.deriving abstract] feature in BuckleScript 3.0.0 and have some feedback:

1.) Thanks, this is great stuff! :slight_smile:

2.) For external function declarations, there is [@bs.string] for turning polymorphic variants into strings. But for fields in a [@bs.deriving abstract] type, this doesn’t work. It would be great to have a mapping between polymorphic variants and strings here, too.

3.) I would like to be able to customize the name of the generated creation function. Currently, the abstract type and the creation function are generated with the same name (the name of the original type).

E.g.

[@bs.deriving abstract]
type user = {
  email: string,
  [@bs.as "first_name"] [@bs.optional]
  firstName: string,
  [@bs.as "last_name"] [@bs.optional]
  lastName: string,
};

produces

  • an abstract type called user and
  • a function also called user with signature (~email: string, ~firstName: string=?, ~lastName: string=?, unit) => user.

However, I want to put everything into a module User and call the type “t” and the creation function “make”.
I can do this with the following “workaround”:

module User = {
  [@bs.deriving abstract]
  type t = {
    email: string,
    [@bs.as "first_name"] [@bs.optional]
    firstName: string,
    [@bs.as "last_name"] [@bs.optional]
    lastName: string,
  };
  let make = t;
};

But I would prefer being able to directly specify a different name for the creation function.


#2

Thanks for the feedback! cc @bobzhang

For 3: aliasing works, but isn’t ideal, since it seems to generate a dead make code: https://reasonml.github.io/en/try.html?rrjsx=true&reason=LYewJgrgNgpgBAVQM4wE5wLxwN4Cg5wDaAAgEZIB0YaAlgG40B2A5nAIbkAuqbAxpwF18cTgE8ADvE6YcwgjGBsaUAFxwk3JswA0comUpskcAEQAzGqg0B9Rm2AwTA-eQohxnGiDtQhBAhZWnABy9jBqGqhauv4uhsYmUEactmFOcW4eXj5+-kkaoQ4RmiwxcAC+ANzCsNKKANbwWJzVVbi4tXCoMEjQ0ljIaBScABQAfgpKUBgmbCbacCMAlEuVQA

Otherwise things this feature has no cost. So yeah, maybe we should provide the renaming capability out of the box?


#3

There is some work around:

type user = { .. } and t = user [@@bs.dering abstract] 

I did think about making a special case to generate name make when its type is t, but it may be too ad-hoc, what do you think


#4

Thanks for your replies.

In Reason syntax, this would be

  type user = {
    email: string,
    [@bs.as "first_name"] [@bs.optional]
    firstName: string,
    [@bs.as "last_name"] [@bs.optional]
    lastName: string,
  }
  and t = [@bs.deriving abstract] user;

right? This doesn’t work for me though. And I don’t see how it would help me with the issue of renaming the creation function.

Would it be possible to have something like

[@bs.deriving abstract("user", "make")]
type user = { ... };

(don’t know if that’s syntactically valid) to explicitly specify the names of the type and creation function to be generated?


#5
type user = {..}
[@bs.deriving abstract]
and t = user;

This isn’t very intuitive, but I think I like this better than another config that fulfills the same purpose? We can document it


#6

@chenglou Thanks, but my main issue is the naming of the creation function, and I don’t see how this can help me here, unless I do

module User = {
  type make = {..}
  [@bs.deriving abstract]
  and t = make;
};

which does give me a type t and a single function make, but feels quite strange. :wink: