1. 8
  1.  

  2. 4

    Is there a conclusion to this article? Reads like it cuts off half way through.

    1. 3

      I think the last sentence and the mic drop gif were the ‘conclusion’. Most of his other posts seem very show-not-tell and end without conclusions. A conclusion would feel out of place with his tone.

      1. 2

        Reads fine to me. Ifs are ugly and cumbersome in Erlang.

      2. 1

        What is the idiomatic way to short circuit logic in Erlang? Or a pattern to restructure short circuit style code into something more “Erlangy”?

        1. 2

          andalso and orelse will short circuit. and and or will always eval both sides. If you want to short circuit your logic use that.

          Relevant section of LYSEFGG: http://learnyousomeerlang.com/starting-out-for-real#bool-and-compare

          1. 2

            I just wrote a reply to the original blog post with that (i.e. with a functional way to implement the same thing described in the article).

            1. 1

              That’s a nice solution for a smaller scale problem, but what about when your conditions are more sophisticated than what’s allowed in guard clauses? And what about a large chain of conditional checks like the andalso example?

              I end up writing code like this:

              case do_thing() of
                  {ok, Result} -> case do_next_thing(Result) of
                                      {ok, NextResult} -> and_so_on_and_so_forth();
                                      _ -> {error, "next thing failed"}
                                  end;
                  _ -> {error, "thing failed"}
              end.
              

              I feel like I must be approaching Erlang with the wrong mentality because I can’t imagine sensible people would write code like this.

              Whereas in Go, this is perfectly reasonable:

              result, err := doThing()
              if err != nil {
                  return nil, errors.New("thing failed")
              }
              
              nextResult, err := doNextThing(result)
              if err != nil {
                  return nil, errors.New("next thing failed")
              }
              
              return andSoOnAndSoForth()
              
              1. 5

                You’re correct. For that code there are many alternatives:

                Use exceptions

                Instead of returning {error, …}, use throw and just write the happy path in your main function:

                Result = do_thing(),
                NextResult = do_next_thing(Result),
                and_so_on_and_so_forth().
                
                Concatenate Functions
                your_fun() -> check_and_and_so_on_and_so_forth(check_and_do_next_thing(do_thing())).
                
                check_and_do_next_thing({error, X}) -> {error, X};
                check_and_do_next_thing({ok, Result}) -> do_next_thing(Result).
                
                check_and_and_so_on_and_so_forth({error, X}) -> {error, X};
                check_and_and_so_on_and_so_forth({ok, _NextResult}) -> and_so_on_and_so_forth().
                

                (I kept your names, don’t blame me :P)

                Use Sophisticated Tools

                You can use something like ktn_recipe to implement your logic.

                1. 2

                  Would you say the concatenate functions method or exception method is more idiomatic?

                  I feel like the concatenate functions method is more idiomatic than exceptions, but I’d be interested in your opinion.

                  1. 3

                    I don’t really have a strong opinion on the subject. I’ve found places where each one of them looks and feels better. The only advice I can give is: do not mix both, stick with just one for your whole project. For what I gather in the erlang community, concatenating seems to be the favourite one, because exceptions are expensive, but then again it’s not like nobody uses them either.

          2. 1

            The short-circuiting evaluation of A andalso B is just syntactic sugar for if A then B else false. There’s no escaping conditionals, you’re only hiding it behind veneer.

            1. 1

              Ok, so I fell down the Rabbit Hole of the Anti-IF campaign.

              It sucked me in because I have long ranted against booleans as a code smell. They are a hint you have some code in the wrong place.

              I also hate if’s from the lispy point of view…. If everything is an expression, what is the type of an if without an else? Or an if with different expressions in each branch.

              Falling deeper into the Rabbit hole, I discovered Francesco Cirillo and his twisty maze of links, all the same, each hinting of insight and enlightenment in programming if you just buy his epub.

              He does have the claim to fame of inventing the Pomodoro technique, he drops the right words that hints he is on The Right Track….

              …but is there anything down there in his twisty maze of links?

              1. 1

                I also hate if’s from the lispy point of view…. If everything is an expression, what is the type of an if without an else? Or an if with different expressions in each branch.

                In an if expression where the else branch should never be evaluated, you can explicitly throw/cause an exception. Languages like SML have functions like raise for explicitly throwing an exception. It takes an exception as an argument and returns a polymorphic value according to its type, so any application of raise to an exception can stand in for a needed expression, but a return value will never actually materialize because of the control flow change of actually throwing an exception.

                The type of an if expression in Lisp can be anything since it’s a dynamically typed language, so both branches can have different types. In statically typed languages like SML, the type constraints of the then and else expressions are determined separately and then unified (basically, handle polymorphic type constraints) to determine a single type for the entire if expression.

                Generally speaking, functional programming tends to not run into scenarios where you have if’s without an else; that’s more of an imperative style.