10 ms·
I'm sorry, but in my decade of JavaScript I never read anything more cryptic than this. What is this supposed to mean?
by whilenot-dev 4y ago
I'm sorry, but in my decade of JavaScript I never read anything more cryptic than this. What is this supposed to mean?
- lolinder 4y agoNot OP, but I've often seen cases where the same set of strings or enum values are used in switch statements in disparate parts of the code base. While each switch is supposed to be checking the same set of values, they invariably end up getting out of sync and checking different subsets of the actual possible set of values, leading to bugs. Some languages support exhaustive switches (typescript has a way to do this), but oftentimes the better solution is to consolidate all of these switches into an object, or a set of objects that share an interface. That way all of the switch statements become function calls or property accesses, and the type checker can warn you at time of creation of the new object if you're not providing all of the functionality the rest of the code will require.
- couchand 4y agoAnd of course, there is no free lunch. You run smack into the expression problem here. The question is: do you have more places that check your conditions than types of options? Are you more likely to add a new check (and need to verify exhaustiveness) or add a new option (and need to modify every check)?
- kevinmchugh 4y agoA switch statement allows you to have different behavior for different inputs, but often all that's needed is different output data. If you have to map, say, country codes to country names, writing a long switch statement of case "US": name = "United States of America" break Is going to suck. An object (in js, an associative array more generally) will be simpler. It's not always quite so obvious as that example.
- aastronaut 4y agoThanks for the example! I guess we consider switch/case in different situations then. I usually make use of switches in simple mappings and switch/case seems more readable and idiomatic to me there: type CountryCode = | "CH" | "US"; function nameFromCountryCode(countryCode: CountryCode): string { switch (countryCode) { case "CH": return "Switzerland"; case "US": return "United States of America"; default: // exhaustiveness checking ((val: never): never => { throw new Error(`Cannot resolve name for countryCode: "${val}"`); })(countryCode); } } ...instead of... type CountryCode = | "CH" | "US"; function nameFromCountryCode(countryCode: CountryCode): string { return ({ 'CH': (() => 'Switzerland'), 'US': (() => 'United States of America'), }[countryCode] || (() => { throw new Error(`Cannot resolve name for countryCode: "${countryCode}"`); }))(); }
- mdaniel 4y agoI'll bite: why the anonymous function throwing an Error in the first snippet?
- aastronaut 4y agoI didn't lay out a bait =) It would also look more readable to me with a default return value. An exhaustiveness check just keeps your mapping functionally pure and the type checker can catch it.
- deleted 4y ago[deleted]
- lolinder 4y agoYour second example is not how anyone here is recommending using an object to replace a switch. You've still got the function call, which is now redundant. Here's how you'd actually do it: type CountryCode = | "CH" | "US"; const countryNames: Record<CountryCode, string> = { "CH": "Switzerland", "US": "United States of America", } Your second example is way more complicated than your first, but this one is even easier to read (at least for me), and still provides all the same functionality and type safety (including exhaustiveness checking).
- ramesh31 4y ago>I'm sorry, but in my decade of JavaScript I never read anything more cryptic than this. What is this supposed to mean? Switches in JS are just implicit maps. const caseVal = 'case1'; const result = ({ 'case1': (()=> 'case1Val'), 'case2': (()=> 'case2Val'), 'case3': (()=> 'case3Val'), } [caseVal] || (()=> 'default'))() Has identical performance to a switch case and is far more idiomatic.
- aastronaut 4y agoThanks for the example! I assume the identical performance just comes from the optimization of the JIT, as allocating objects in the heap seems quite overkill for such a control flow. I only fall back to this when switch/case isn't available in the language, eg. in Python. Is this a thing in the JS community?
- svieira 4y agoIt's not in JavaScript, but see Unifying Church and State: FP and OOP Together for another example of the "switch / named functions" (or "Wadler's Expression Problem") described in a pretty intuitive way: https://www.youtube.com/watch?v=IO5MD62dQbI https://www.youtube.com/watch?v=IO5MD62dQbI
- aastronaut 4y agothere goes my evening, that's what I like about HN. thanks for the refs!