Private by default

How would people feel if everything was private by default in ReScript instead of the opposite?

Using a signature file to hide details feels cumbersome, especially since I often use this for React components. This requirement is necessary for fast refresh to work, and it all feels a bit backward to me.

What if ReScript had an export keyword like JavaScript? Then public information could be determined explicitly instead.

1 Like

I met someone today who was complaining that Rust requires pub to be added everywhere :joy:

I suppose you read: RFC: private by default for values ?

I think we are a bit hesitant to do such a big change after the massive “uncurried by default” change.

Other than that there are benefits in interface files concerning compilation speed. It’s basically the secret sauce for scalability.

That said I wholly agree that it’s not a great fit for everything that utilizes fast refresh. But I also think it is great for prototyping if you don’t need to export every single function separately.

2 Likes

I’d be happy with a private keyword instead of having to make a .resi file. I have gotten used to the .resi files, but it’s not super intuitive to JS programmers.

private let x = 42`

There is a syntax for private let bindings, but it allows multiple values like a module would.

That way you don’t need to put private before every value.

%%private(
  let x = 42
  let y = 1
)
1 Like

Perhaps I’m more looking for a Vite plugin that simply removes any exports.

It shouldn’t be too difficult to remove sum from

export {
  sum,
  CounterMessage,
  App,
}

This avoids the need for any changes on the ReScript side and effectively resolves the issue in the relevant problem space.

1 Like

Like this: GitHub - egoist/vite-plugin-remove-exports: A Vite plugin to remove certain exports ?

While I would prefer a “private by default” setting I mostly don’t care.
Sometimes I try to use the %%private approach, but my LSP doesn’t work for code inside. So I use a nested module to “hide” the functions etc.

Is it a known issue?

I’m using neovim with @rescript/language-server@1.58.0

Sounds like something that should be fixed in the LSP indeed. Would you log an issue on the tracker?

Yeah, you are right this was never solved:

Last comment in that third issue is key:

cristianoc on Apr 30, 2021
We need a better representation rather than apply reverse reconstructive surgery in the IDE.

I think that is still not improved, but nowadays as both the LSP and the compiler are developed alongside in the same repository, we might have a shot at this?
@cristianoc @zth

Oh, right, forgot about those. I think the assessment @cristianoc has still holds - we should find a better representation for this instead. And yeah, I think we’re better off than ever to do that now that we’re getting our own AST.

3 Likes

So I did some digging to transform the JavaScript code to remove the export.
It is possible to transform the code, remove the export of the JavaScript side.
However, the approach didn’t work for the following scenario:

Main.res

switch ReactDOM.querySelector("#root") {
| None => Console.log("Root element not found")
| Some(rootElement) => {
    let root = ReactDOM.Client.createRoot(rootElement)
    ReactDOM.Client.Root.render(
      root,
      <React.StrictMode>
        <Settings />
      </React.StrictMode>,
    )
  }
}

Settings.res

@react.component
let make = () => {
    <div className="bg-primary-500 h-100">
        {React.string("Settings y")}
    </div>
}

Changing Settings.res did result in a change in Main.res.mjs.
The file timestamp is different and Vite picks this up.
When there is a signature file for Settings.res, this does not happen.
Ergo, signature files are necessary for fast refresh to work.

(You could easily test this when with bun create rescript-app@next, removing App.resi will no longer allow hmr to work)