Live data from Hacker News

Anti-if: The Missing Patterns

code.joejag.com

41–50 of 74 posts

Re: Anti-if: The Missing Patterns

#41
I'm quite supportive to the anti-if pattern but the presented example sounds me more like "code smells" and doesn't really makes me happy to me anti-if is a great winner when you can safely compute all the execution path in advance (in a way where you have not to nest ifs, of course!) but in situations where your code have to react to something that happens "on the moment"... well, probably "if" are more convenient (not always of course) anyway thanks to have raised the point, this topic is always interesting to me

Re: Anti-if: The Missing Patterns

#42
post #2

> Context: You have a method that takes a boolean which alters its behaviour > Problem: Any time you see this you actually have two methods bundled into one. That boolean represents an opportunity to name a concept in your code. This is only true if you're using literal booleans at you call sites. If the booleans are coming from somewhere else, like user input, you just moved your single if statement in the method ou…

Common Lisp to the rescue! (defmethod make-sound ((b bear) (loud-p t))) ;; bear makes loud sound ...) (defmethod make-sound ((b bear) (loud-p null)) ;; bear makes quiet sound ...) If we call (make-sound bear-instance nil), the second method is invoked because loud-p is specialized to the null class, whose only instance is nil. (There is a type nil also, whose domain is the empty set: it has no instance.) If we call (…

Also known as multiple dispatch, which is supported by many languages: https://en.wikipedia.org/wiki/Multiple_dispatch

Re: Anti-if: The Missing Patterns

#43

Earlier quoted context omitted.

> The point of passing boolean params instead of named functions is that most of the time there is shared code between the two paths and not literally all the code is enclosed in either the if or the else block If you have this method(bool arg) { // block A if (arg) { // block B1 } else { // block B2 } // block C } you can replace it with method1() { A(); B1(); C(); } method2() { A(); B2(); C(); } where A(), B1(), B2…

> This makes the code clearer, IMO. Depends on how much state you need to pass between A, B1, B2 and C.

It also depends on the semantic value of A, B1, B2 and C. If you cannot express them as senseful steps of your overall algorithm, then you are bound to end up with very confusing method names like calculateFooAndCreateBarAndAlsoInitializeBaz, or (even worse) prepareForFoo.

EDIT: By the way, an anecdote. Years ago, I was working with an offshore developer who was producing huge scripts without any modularization whatsoever. In particular, we told him that a certain 2000-line script needed to be modularized, so he should break out steps into functions etc. He produced a new version containing two functions of 1000 lines each. The first function would prepare everything, then tail-call the second function with 27 arguments, most of them large intermediate data structures.

Re: Anti-if: The Missing Patterns

#45
post #37

All these complicated examples and no mention of functional pattern matching or pattern matching at all. IMHO These are by far the two most important ways to get rid of complex code embedded with ifs. One very good example of this is erlangs factorial method. factorial(0) -> 1; factorial(N) -> N * factorial(N-1). There are many other nice examples at the erlang documentation: https://www.erlang.org/course/sequential-…

True functional-style pattern matching is only slowly coming into imperative languages right now, most prominently in Rust.

Re: Anti-if: The Missing Patterns

#46
post #5

This reminds me of something I read on HN a while back and forgot to bookmark. (Naturally I've been unable to find it since.) I think the article was written by a company who made a static code analysis tool. They described how there wasn't a large difference in quality between FOSS and proprietary code, except for one detail: FOSS code used "else" statements much less. Anyone have any idea what I'm thinking of or if…

Did you try http://hn.algolia.com ?

Re: Anti-if: The Missing Patterns

#47
post #37

All these complicated examples and no mention of functional pattern matching or pattern matching at all. IMHO These are by far the two most important ways to get rid of complex code embedded with ifs. One very good example of this is erlangs factorial method. factorial(0) -> 1; factorial(N) -> N * factorial(N-1). There are many other nice examples at the erlang documentation: https://www.erlang.org/course/sequential-…

Unfortunately, pattern matching isn't available in many languages (or at least, including a new dependency for the sake of removing `if`s may not be worth it).

On the other hand, the article recommends using sub-type polymorphism, which is also unavailable in many languages.

Re: Anti-if: The Missing Patterns

#48
post #12

If you want extreme case of removing all ifs, see how ifTrue: and friends are implemented in Smalltalk (ie. true and false are instances of different classes), although essentially all compiler implementations turn that into normal conditional branches in generated bytecode.

Also, from the functional programming side, Church Booleans:

    function  true(x, y) { return x; }
    function false(x, y) { return y; }
There's an example of Church encoding used in anger at http://www.haskellforall.com/2016/04/data-is-code.html

Re: Anti-if: The Missing Patterns

#49
post #24

Getting rid of if/else is nothing but moving the if/else to somewhere else.

This is only true in a very technical sense. function getColor(str){ if(str=='blue'){ return '#0000ff'; } if(str=='red') { return '#ff0000'; } } getColor = { blue: '#0000ff', red: '#ffoooo' } The second one also has if statements inside the implementation of the hash map, but it isn't actually polluting your business logic. The question is no longer "what do you do when the input is like this or like that", but "look…

I agree. For example when you are using some form of polymorphism, the compiler/runtime are handling your if/else for you. But, still in terms of understanding what a piece of code is doing you will have to consider all the possible branches whether they are explicit in code as if/else statements or hidden under some abstraction like map/dictionary.

Edit: The conditional abstractions like map are useful in the sense that the conditions that they support are very simple, in case of map it is if supplied key equals that key, whereas if/else statements can be used to create any kind of complex conditions.

Re: Anti-if: The Missing Patterns

#50
post #5

This reminds me of something I read on HN a while back and forgot to bookmark. (Naturally I've been unable to find it since.) I think the article was written by a company who made a static code analysis tool. They described how there wasn't a large difference in quality between FOSS and proprietary code, except for one detail: FOSS code used "else" statements much less. Anyone have any idea what I'm thinking of or if…

That does sound familiar. Was it possibly from either the NDepend blog, or more likely, the PVS-Studio blog?
Post reply on HN