I decided to learn a spot of Erlang, swayed mainly by the excellent Learn You some Erlang for Great Good! (Which is even better than it's Haskell namesake). As ever, I needed a little learning exercise rather than just read through six-hundred odd pages and so decided to work on a little idea I had for awhile: A command line / console based weather application because the Met Office site isn't great in Elinks (mobile site works, but doesn't give me the detail I want). Is Erlang the correct language for this? Almost certainly not (for starters I make no use of the concurrency aspects of Erlang), but why let that deter me?

As it is right now it is purely a command line application, isn't ever likely to offer any GUI and provides less information that the Met Office mobile site, but the fundamentals are there for me to add to.

So far, I have to say that I like Erlang. It's like Haskell, but a bit easier - Although I don't know for sure whether I found it easier because of having previously played with Haskell or whether it really is easier. I suspect it is a bit more simplistic and therefore also more verbose. And on that note the code can be a bit messy, but there is definite structure to the mess. Equally, I could be talking rubbish.

Some things I found interesting about Erlang

Can't use functions in arguments

Which adds to the verbosity. I.e. I've had to do this:

Headwind = lists:member(Heading, Headwinds),
Sidewind = lists:member(Heading, Sidewinds),
Tailwind = lists:member(Heading, Tailwinds),
if Headwind ->
    io:format("Heads you lose!~n");
Sidewind ->
    io:format("It's a draw~n");
Tailwind ->
    io:format("Tails you win!~n")

instead of being able to do this:

if lists:member(Heading, Headwinds) ->
    io:format("Heads you lose!~n");
lists:member(Heading, Sidewinds) ->
    io:format("It's a draw~n");
lists:member(Heading, Tailwinds) ->
    io:format("Tails you win!~n")

Which is something to do with guard expressions it seems.

Pattern Matching Everywhere

This I like. How do you deal with optional arguments? You don't, you just write the function again. I really like this idea - it's nice and simple. As an example, when running from the command line the arguments (however many) are sent as a list ([1, 2, 3, 4, etc]) so if you have your function set up to take a couple of arguments you just write a new version of the function that takes one list, splits out the arguments and then calls the other version of the function. Like so:

headsilose([Location, Heading]) ->
    headsilose(Location, Heading).
headsilose(Location, Heading) ->

Underscore prefixes for stuff you don't want to use

I knew about the use of _ from Haskell, but in Erlang (I don't know if the same for Haskell?) you can use the underscore as a prefix so you can still have some context:

Like here, where I only care about Hours:

{{_Year, _Month, _Day}, {Hours, _Minutes, _Seconds}} = Date,

but that is infinitely more helpful than:

{{_, _, _}, {Hours, _, _}} = Date,

Although it should be noted that it is still binding these variables so you can't re-use (re-assign) them - it just makes the compiler stop warning that you've not used them elsewhere.

Atoms (and uses in pattern matching)

Atoms are a bit like extensions of booleans True and False, well at least from a pattern matching point of view. Here the atom ok is used to pattern match against a successful HTTP request:

{ ok, {_Status, _Headers, Body }} = httpc:request(URL),

So that Body will only ever get something to assigned to it if the request is successful. What I should also do (but haven't yet) is pattern match against the error case so I can handle that, i.e. like so:

    { ok, {_Status, _Headers, Body }} = httpc:request(URL)
    error:{badmatch,{_,_}} -> do_something_else

Anyway, there you have it, I've learned myself some Erlang for great good.