syntax
syntax copied to clipboard
Feature suggestion: syntax for Js.Dict.t literals
I've been working with code that uses "hash map" style JS objects, and the ReScript syntax for declaring them can be tedious. (Or rather, the lack of syntax to declare them is tedious.)
Consider this JS:
const data = {
a: foo,
b: bar,
c: baz,
};
Compared with this ReScript:
let data = Js.Dict.fromArray([
("a", foo),
("b", bar),
("c", baz),
])
That's a lot of extra parentheses and brackets to express the same thing. When you inline it somewhere (such as inside a function argument), then it's even more noisy and less readable.
My suggestion is to include a dedicated syntax similar to Js.t objects. Maybe something like this:
@dict
let data = {
"a": foo,
"b": bar,
"c": baz,
}
Would this make sense to add?
I think we could even have a generic system for simple, literal keys:
// Js.Dict
dict{
"a": 1,
"b": 2,
"c": 3,
}
// Belt.Map.String
map{
"a": 1,
"b": 2,
"c": 3,
}
// Belt.Map.Int
map{
1: 1,
2: 2,
3: 3,
}
set{1, 2, 3} // Belt.Set.Int
set{"foo", "bar", "baz"} // Belt.Set.String
That would be cool if it was possible, although that would have to still desugar/compile to function calls, right? Js.Dict can potentially compile to an object literal, which seems much simpler.
I think I saw an issue on the compiler that @bobzhang opened some time ago that discussed the possibility to convert ˋfromArray` calls with literal to the data structure itself. I think it'd be fairly easy for dicts, but not sure about Belt data structures.
@bloodyowl: Love this approach!
@bloodyowl if calls to Js.Dict.fromArray with a literal array would be compiled directly to the given json object then it would totally make sense to have a dedicated syntax. But I wouldn't mind the slight runtime cost meanwhile.
I couldn't find the issue though, are you talking about rescript-lang/rescript-compiler#2320 ? It's more than 3 years old, I hope it'll get more love now ^^
@bloodyowl I would very much be in favor of that.
My use case in case there's a better way
module Icon = {
@react.component
let make = (~icon: option<string>=?) => {
<img src={icon->Option.getWithDefault("/img/default-icon")} />
}
}
module LabelWithIcon = {
@module external hobbyIcon: string = "./hobby.svg"
@module external memoryIcon: string = "./memory.svg"
@module external standardIcon: string = "./standard.svg"
let icons = Js.Dict.fromArray([
("Hobby", hobbyIcon),
("memory", memoryIcon),
("standard", standardIcon),
])
@react.component
let make = (~id: string, ~label: string) => {
<label><Icon icon={icons->Js.Dict.unsafeGet(id)} />{label->React.string}</label>
}
}
My rationale is that explicitly typing all the possible ids with a Record would be rather tedious. Additionally by definition of this type it does not really matter if an icon displays or not, it's a nice-to-have, but no one is going to miss them if they don't display. The fromArray works but it's a bit of a roundabout way to get there so a direct syntax would be awesome!