Skip to content

Instantly share code, notes, and snippets.

@7-fl
Last active May 7, 2017 03:38
Show Gist options
  • Select an option

  • Save 7-fl/db18e7ccb88d3540fbafbda71b6478d9 to your computer and use it in GitHub Desktop.

Select an option

Save 7-fl/db18e7ccb88d3540fbafbda71b6478d9 to your computer and use it in GitHub Desktop.
What do you think about Erlang?

What is most difficult about learning Erlang? (And what’s easiest?)

Difficult: Recursion, Reading other people’s code.
For some problems, I find it exceedingly difficult--and sometimes I’m unable--to figure out a recursive, stateless solution. That kind of shakes my confidence. While for other problems, I can quickly envision a solution, and I start writing code immediately.

When the solutions got more complex, it was tough to debug my own code--much less somebody else’s, so I found it hard to review other people’s code--even though I was already intimately aware of the issues involved in solving the problem. Judicious commenting helped. Tests helped. Then if things were still unclear, digging in and manually following the function execution with some real values helped. If I hadn’t already solved the problem first, I doubt I would have been able to decipher what the heck was going on. I think it would be really hard to revisit someone else’s solution in six months and try to understand the code. So I guess I don't find erlang code that easy to reason about--contrary to the common refrain. Even a couple of beautiful tail fib() solutions I reviewed, which involved 3-4 lines of code seemed liked they couldn't possibly work correctly, and I had to test them to make sure they did in fact work correctly.

Easiest: Syntax, Pattern Matching, Tail Recursion.
Once I learned the accumulator pattern, my fist choice was to use tail recursion to solve problems--because it felt more natural to me. Using tail recursion, I could add as many “varying” variables as I wanted to the parameter list, then I could use those variables to hold state, e.g. adding terms to an accumulator variable.

In the master class video, Mr. Cesarini commented that at first students use if-statements and case-statements, then he shows them how to use pattern matching in the head of function clauses instead. I’ve been trying to come up with alternate solutions that “smash” my case and if statements into function clauses, and sometimes I like the result, and sometimes I don’t. In any case, pattern matching feels natural to me, and it’s one of the features of erlang that I really enjoyed learning about.

What are the advantages and disadvantages of the functional programming approach?

I’m still in the beginner phase of learning a computer programming language, where I keep my head down and concentrate on adding to my bag of tricks, so my observations are about some technical details.

I was perplexed when Joe Armstrong said that you don’t need a debugger for erlang. When an error’s stack trace is three function calls deep, and some of my functions had five parameters, it was hard to figure out where the problem was. For instance, an error message alerted me to the fact that a function was getting a single item when it should have been getting a list of items. So I scoured my code trying to figure out where I was peeling off the first element of a list and using that value instead of a list of values, but I couldn’t readily identify where that was happening. A debugger would have enabled me to step through my code watching the offending variable until its value changed from a list to a single value. It took me a couple of hours to debug that. In addition, I’ve used erlang’s debugger before in a multiprocessing solution, and as far as I could tell, it was a critical tool.

I find that erlang’s “base” syntax:

     2#1110

hasn’t kept up with improvements in other languages. Numbers using the base2 syntax can be hard to visually separate into bytes when the numbers get bigger:

    2#11101101010110

which is error prone when writing them and reading them. Ruby and perl and python’s latest 3.6 release, all allow an underscore to be used in a number:

    0b1101_1000_1010_0001

That is extremely convenient, and I wonder if erlang is considering adding that feature?

I wish the class had also covered:

  1. binaries
  2. maps
  3. list comprehensions

They all have some really interesting features. For instance, I think pattern matching is one of the really greate features of erlang, and binaries allow you to use pattern matching to unpack the bits of integers, when integers are used as a message. Using binaries and pattern matching you can separate an integer into chunks of bits whose meaning has been defined in a protocol.

We could have used binaries to come up with an alternate solution to the bit_sum() function in one of our assignments(week 1?):

bit_sum(N) when N>=0 ->
    IntToBinary = binary:encode_unsigned(N), %Converts an int into something called a 
    bit_sum(IntToBinary, 0).                 %”binary”, which is a view into an
                                             %integer’s bits.
bit_sum(<<>>, Sum) ->
    Sum;
bit_sum(IntToBinary, Sum) ->
    <<X:1, RemainingBits/bitstring>> = IntToBinary,  %Pattern matching “binaries”
    bit_sum(RemainingBits, Sum+X).

In that code, << >> is analogous to a list’s [ ], and the code removes the first bit of a “binary”, X:1, just like removing the head of a list. The recursion removes one bit at a time until the binary is empty <<>>, which is analogous to an empty list []. Along the way, the code adds the removed bit, whose value is 0 or 1, to an accumulator variable Sum. Not specifying the size for RemainingBits is analogous to using * in a regex: it matches the rest of the bits. Easy, peasy.

When might you use Erlang in preference to another language?

For everything right now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment