Rescript-compiler: Expand %private to module definitions

Created on 9 Apr 2020  路  5Comments  路  Source: rescript-lang/rescript-compiler

I took the example from the announcement blog post:

module A = struct
  [%%private let a = 3]
  let b = 4
end

And attempted to expand it to the entire module definition:

[%%private module A = struct
  [%%private let a = 3]
  let b = 4
end]

Reason even has syntax support for this, judging by what happens on https://reasonml.github.io/en/try, but the website comes back with Uninterpreted extension 'private'. (in my project the compiler is reporting the structure is not supported in local extension).

I have started using local modules to namespace types and externals, so as a result I end up with a lot of var A = {} in my generated JS which cannot be removed with tree shaking (I may eventually add interface files but that would be inconvenient at the moment). Having private support would be a big help!

Most helpful comment

there are some subtlety to support private modules since types in modules may be escaped, but we will revisit later

All 5 comments

there are some subtlety to support private modules since types in modules may be escaped, but we will revisit later

Just to elaborate a bit on the original post, having %private type would also be great (not sure how hard it'd be):

type%private t = ...;

// Additionally to

module%private X = ...;

Also (on a slightly different note), I find myself using opaque types quite often, and having to write an interface file just for that is rather unergonomic:

type t = int;

let whatever: t => string = ...;

// and in the interface file
type t;

let whatever: t => string;

Would there be a way to have an %opaque "modifier"?

type%opaque t = int;

So that t is exported as t, not as t = int.

I don't agree with extending private to types. The feature is not designed to _replace_ interface files, just make a few simple cases easier to develop without them.

Abstract t is the big use case for having an interface file; this way the implementation doesn't need to know or care that the exported type is abstract.

I don't find it unergonomic at all, but I've been writing Reason/OCaml for 6 years so I am very much used to it. I also _never_ use local type annotations in implementations unless the compiler forces me to, which is another habit I see coming from TypeScript developers a lot (understandably, due to how TS type inference works). This is another practice that interface files help with; there is no need for local annotations to prevent accidentally changing the function type.

we will revisit this when we upgrade compiler upstream

@bobzhang if you upgrade to 4.08+ upstream then this issue will become moot due to open struct ... end functionality. E.g.

open struct
  module A = struct
    let a = 3
    let b = 4
  end
end

let () = print_int (A.a + A.b)
Was this page helpful?
0 / 5 - 0 ratings