Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

There are multiple alternatives to switch (or if) statements and I would generally agree switch statements are mostly a code smell. As one posters described, using the fall-through behavior is more what justifies it and the real difference. I know you asked for ELI5, but let me give you some options to think about how you code on a broader level and how to eliminate both if and switch or at least improve them.

If you think of a switch statement as a pattern matching construct, then you will realize there are many, many alternatives in any programming language, including Python. For instance, the dict method works, as can anything that operates a collection-oriented data structure. For example, you could just as easily loop on a list and do this too, but for most lists this would require a worst case of O(n) iterations where n is the size of the list to match, thus a dict is better. A dict would not work if you want fall-through since you would only be matching on a single key usually, unless once again you do lookups of multiple keys (dict still wins). But a list would support this fall-through behavior with minimum effort and a small list would preform alright.

If your usage is lets say more sophisticated than a key lookup, there may be alternative data structures that you can use to achieve similar results (b-tree, red-black tree, skip list, etc.) though that is of course getting further from the usual behaviors of switch statements.

A functional way to go about it would be to reduce or fold on some collection. If you think about the items that don't match, they wouldn't add anything into the final reduction much in the way map/reduce works traditionally. Many times this would just consolidate the entirety of the function you are calling the switch with the result it is producing. Generally, I'd encourage thinking of writing code that operates on data and thus tends to make good reduce of things like reduce, map, filter, etc. as this often simplifies things and in some cases can actually lead to nice performance if done right. It also tends to force you to write things atomically, with less side-effects, and as pure functions. One of the problems people have with if-statements is they end up burying unrelated concerns or bug-inducing side-effects in each if/else or each branch. This code smell is easy to detect by simply pretending you are looking at new functions for each piece of code under an if/else or case and seeing if they are returning the same "type" in general sense of thing, how much there is in common between each piece, and if they are doing 1 or multiple things each. Most of the time, you are really doing the same thing with one slight difference like an input parameter, and you never really needed an if or at the very least, it could be handled differently. If you are doing more than one thing per if, it often means you are doing too much. Furthermore, you should test that if you were to repeatedly pass the same data to each, would you get the same result?

Another way of handling this is to use multi-methods. Note that in truth, it's the same as above because all you are doing depending on your implementation is pattern-matching. It just depends if your behavior is match one or match multiple (fall-through-like). Python can use attributes to do multi-methods among a few other ways. It's been awhile and mostly I'd avoid using them for performance reasons, but it's another option when thinking of more advanced ways to get rid of switch or if constructs.

In general, it's worth noting that in many languages such as Python, though ifs/switch might be ugly, they can often perform pretty well. It is also worth knowing that if/switch are not very good for functional styles sometimes. Making lists or dicts or other constructs is not always free, or slower/faster so it can sometimes just be a balance between performance, clarity, and composition.

Hopefully that gets you thinking and is not too confusing. A bit exhausted so I'm not thinking my best, though I think I am sending you down a track to explore to help you grow.



Thanks for the write-up. I've had to re-read a couple of bits, but that's how you learn :)

My switch use to date has almost entirely been about parsing commandline args - one of the two time I didn't do that was when my colleague talked about the code smell.

It's been interesting watching how new areas in programming just unfold potential in front of you as you learn. My bash scripts used to be relatively simple, serial things, then a mentor forced me to start using functions - and that was eye-opening. Things made more sense, and not least because I had to keep less 'state' in my head. You mention map and similar, and this is something I haven't really touched yet, but it sounds like it'll help some of the things I do (mostly ops scripts).

Thanks again for the write-up.


It sounds to me like you also need to start focusing on atomic functions and abstractions more in general. Your functions should do one things as I mentioned.

Regarding "map," "reduce" is probably the one you want to learn first because you can express many functional constructs like "map" in terms of "reduce."

As a general word, parsing command lines almost always tends to be ugly. My general advice here would be to use the built-in stuff or at least a well-used library as much as possible. If you are finding that you are doing a lot of work yourself or using reg-exs that you made, that's often a side that you are doing something wrong.

Anyway, lots more but I don't want to overwhelm. Good luck!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: