Improve JavaScript field accessors
Opened this issue · 3 comments
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).
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.
@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
) ?
Yes I think so! I intend to generate .d.ts files from Gleam code but the other direction could also work.