gleam-lang/suggestions

Improve JavaScript field accessors

Opened this issue · 3 comments

Aloso commented

Right now the JavaScript examples use Reflect.get and Reflect.set to access JavaScript fields. This has two problems:

  • It is cumbersome to write
  • The generated JS code is inefficient

The second problem could be fixed by special-casing the Reflect API when emitting JS. To fix the first problem, a different syntax is needed.

My first idea was, why not use the same syntax as in JavaScript?

document.body.add_event_listener("click", fn() {})

However I'm not sure if this would work because the dot is already used for module items. Another option would be a variation of the pipe:

document |. body |. add_event_listener("click", fn() {})

JavaScript also allows fields that aren't valid identifiers, which can be accessed using square brackets, e.g. foo["bar!"]. Likewise, Kotlin accepts invalid function names, if they're surrounded by backticks:

fun `hello world!`() {}

This would be useful in Gleam as well, for example:

document
  ["body"]
  ["addEventListener"]("click", fn() {})
// or
document
|> "body"
|> "addEventListener"("click", fn() {})
// or
document
  ."body"
  ."addEventListener"("click", fn() {})

Another question is what should happen when this syntax appears in a file that is compiled to Erlang. My idea is to desugar it to |> get("..."), so it can be used even when targeting Erlang, as long as a get function is in scope (similar to how JSX is desugared in React.js).

lpil commented

Hello! Thanks for your suggestions

It's not recommended to use reflect, rather wrapper functions are preferred around JavaScript code that needs to do anything complicated. I think the examples I previously wrote were misleading but I was trying to fit it in the blog post and we did not know what is best for FFI here.

In future we will have documentation on how to use the FFI with both Erlang and JavaScript, which will help.

We are unlikely to add any special syntax for working with JavaScript or Erlang values I'm afraid, we prefers to have a hard boundary between the host language and Gleam in order to keep Gleam as simple as possible and to avoid having multiple ways of expressing roughly the same thing.

Aloso commented

@lpil thanks for clarifying! I'm looking forward to this documentation!

Another question: Would it be theoretically possible to create JS -> Gleam bindings automatically, perhaps based on a typescript definition file (*.d.ts) ?

lpil commented

Yes I think so! I intend to generate .d.ts files from Gleam code but the other direction could also work.