DEV Community

Cover image for Why I prefer objects over switch statements

Why I prefer objects over switch statements

Enmanuel Durán on February 17, 2019

Recently (or not so recently, depending on when you read this article), I was having a debate with some teammates about how to handle conditions ...
Collapse
 
davidchase profile image
David Chase

good article, ive been doing similar recently but i used es6 Maps and dynamic keys

const fn = n => new Map([
  [n < 2, 'Less than 2'],
  [n === 3, 'Equals 3'],
  ['_', 'Some default value here']
])
Enter fullscreen mode Exit fullscreen mode

i use _ as a default value and a little helper like

const cata = map => map.has(true) ? map.get(true) : map.get('_')
cata(fn(3)) // Equals 3
Enter fullscreen mode Exit fullscreen mode
Collapse
 
maxart2501 profile image
Massimo Artizzu

Nice.
On the down side, you have to be careful that no more than one condition is verified.
On the plus side, '_' looks like a confused face 😐😀

Anyway, you can do that with objects, too, but booleans would get converted into strings.

Collapse
 
davidchase profile image
David Chase

haha just setup a quick example :)

Collapse
 
hdennen profile image
Harry Dennen

Is there a specific benefit of this functional approach? Seems to accomplish the same thing but it took me longer to work out what it was doing.

Collapse
 
thomasjunkos profile image
Thomas Junkツ

I though the same: Clever but without practical use.
Reading the code fluently comes here to an unnecessary halt.
map.has(true) ? map.get(true) : map.get('_') Reading this in a codebase makes me go WTF?!.

Thread Thread
 
davidchase profile image
David Chase

it depends on the codebase, again it was a quick example to showcase another alternative way :)

Thread Thread
 
thomasjunkos profile image
Thomas Junkツ

I tend to disagree. It mainly depends on your target audience.

Of course you could have a codebase where you enforce functional paradigms - which in itself might be not the worst idea. But in the context of Javascript this code above looks like shenanigans, stuffing patternmatching down the reader's throat. It is cool, that you found a way making your beloved pattern available in Javascript, but as I said above it disturbs the reading flow, because it makes you spent extra time to decipher what you intended.

A different example is the use of map and filter, which is native to the language: Although it might take some time for the untrained reader which was socialized with his for-loop to understand; but anybody fluent with the language does immediatly know what was intended.

For me it is a real time saver having code which is easy to read, easy to understand and therefore easy to debug.

I know it is fulfilling beating the language and making things happen, but the downside is oftentimes beating the language is beating the reader.

No offense. It might sound a bit harsh, but read it written with a mild undertone ;)

Thread Thread
 
davidchase profile image
David Chase

Sure I tend to agree if folks are familiar with functional paradigm and as you mention pattern matching etc then it’s a little easier and sure I probably could have kept the cata out where it looks in the Map and pulls out either when the condition is true or the default value.

I took no offense. Everyone is entitled to their own opinions.

I just got excited when I saw the post to share an alternative, which may not fit your interests or needs etc but I decided to share anyway and would do it again :)

Collapse
 
davidchase profile image
David Chase

Just a quick example of an alternative to the OPs object hash its similar to clojuredocs.org/clojure.core/cond or if you prefer JS ramdajs.com/docs/#cond

Collapse
 
oscherler profile image
Olivier “Ölbaum” Scherler

I agree that when a switch statement is used to perform a mapping (which is not always the case), then it’s usually better to replace it with an actual mapping. But we should also keep readability in mind. Your last switch statement immediately shows what it’s doing. The object approach is less immediate.

(Also, pattern matching is not an ES6 proposal, it’s an ancestral FP principle that’s proposed for addition to ES6.)

Collapse
 
qm3ster profile image
Mihail Malo

My favorite is that if the object is in the outer scope, you can statically link to a value instead of having a function call with a hardcoded string argument.
In many cases this enables making definitions not recursive, like the example in my post:

I just wish other people were more accepting of this approach.
That's not always the case :v

I am glad you mentioned the pattern matching proposal, in my opinion the closest implementation of it in current JS is actually the early return pattern:

const aMatchingFunction = arg => {
  if (typeAssertion(arg)) throw new Error(`Bad types`)

  if (matchPredicate1(arg) return matchBody1(arg)

  if (matchPredicate2(arg) return matchBody2(arg)

  const {param} = arg
  if (param && matchPredicate3(param)) return matchBody3(param)

  throw new Error(`No match, got ${arg}`)
}

It looks imperative at a glance, but with just a little discipline it serves the role very well.

Collapse
 
squgeim profile image
Shreya Dahal • Edited

I tend to do this in JS as well, but it was more of a habit I carried from Python, which does not have switch..case and the common way to replicate that behavior is to use objects (dicts).

I would put the cases in a closure instead of the function itself to save some memory (granted it's a tiny bit).

const getEditorType = (() => {
    const itsCodeEditor = () => 'It is a code editor';
    const itsIDE = () => 'It is an IDE';

    const editors = {
        atom: itsCodeEditor,
        sublime: itsCodeEditor,
        vscode: itsCodeEditor,
        webstorm: itsIDE,
        pycharm: itsIDE,
        default: () => 'unknown'
    };

    return type => (editors[type] || editors.default)();
})();
Collapse
 
itr13 profile image
Mikael Klages

It's kind of interesting that the way you use objects here allow you to write code similar to how switch statements work in some languages.

As an added bonus, writing it like this may let you implement a different feature present in some languages, that checks if a switch has covered all possible inputs (usually used with enums). This could prevent stuff like, having one entry misspelled, or somebody adding something somewhere, but not updating all the linked "switch"es.

Though depending on the implementation, this may be even more work or cause more trouble.

Collapse
 
chiangs profile image
Stephen Chiang

I tend to use this method for very predictable objects that otherwise would have been unnecessarily long switch statements. Good stuff

Collapse
 
hdennen profile image
Harry Dennen

I agree with this. Switch statements have a place but more and more my team has been implementing this kind of strategy pattern instead.