Contribution Question: Zero-cost vs ReScript developer ergonomics #23
-
The DOM APIs generally have a lot of ways to interact with them, and sometimes with a little more overhead could be make a lot more usable. For example looking at the various @send external getEntries: t => array<performanceEntry> = ""
@send external getEntriesByName: (t, string) => array<performanceEntry> = ""
@send external getEntriesByType: (t, string) => array<performanceEntry> = ""
@send external getEntriesByNameAndType: (t, string, performanceEntryType) => array<performanceEntry> = "getEntriesByName" but this could easily be abstracted to: let getEntries = (t, ~name: option<string>=?, ~entryType=?) => switch (name, entryType) {
| (Some(name), Some(entryType)) => _getEntriesByNameAndType(t, name, entryType)
| (Some(name), _) => _getEntriesByName(t, name)
| (_, Some(entryType)) => _getEntriesByType(t, entryType)
| _ => _getEntries(t)
} Another example would be /**
* This throws an exception if the string passed is reserved in the PerformanceTiming API
*/
@send external _markExn: (t, string) => unit = "mark"
let mark = (t, name) => {
switch name {
| "navigationStart"
| "unloadEventStart"
| "unloadEventEnd"
| "redirectStart"
| "redirectEnd"
| "fetchStart"
| "domainLookupStart"
| "domainLookupEnd"
| "connectStart"
| "connectEnd"
| "secureConnectionStart"
| "requestStart"
| "responseStart"
| "responseEnd"
| "domLoading"
| "domInteractive"
| "domContentLoadedEventStart"
| "domContentLoadedEventEnd"
| "domComplete"
| "loadEventStart"
| "loadEventEnd" => Error(InvalidName)
| x => Ok(_markExn(t, x))
}
} Question being, should |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I think zero cost should be our goal, but there are existing examples where ergonomics are preferred (although many of those were written before the type system added things like records-as-objects and polymorphic-variants-as-strings). So it's probably best described as "on a case-by-case basis". In your two examples, |
Beta Was this translation helpful? Give feedback.
I think zero cost should be our goal, but there are existing examples where ergonomics are preferred (although many of those were written before the type system added things like records-as-objects and polymorphic-variants-as-strings). So it's probably best described as "on a case-by-case basis".
In your two examples,
getEntries
seems better as zero cost (this style of binding is fairly common for flexible-argument JS functions) andmark
is... arguable. The overhead of bundling all those names, and keeping them up to date if the standard changes, doesn't seem worth it.