Interesting And Unexpected Benefit Of Pattern Matching

So recently I’ve been working on automating some interactions with a website.  Elixir’s Hound library is a great help, of course.  But I also ran across an interesting and unexpected benefit to pattern matching that greatly simplified some code.

I was trying to dynamically build a URL to pass parameters. The URL would be in the form:

http://www.exampledomain.com?param1=p&param2=q&param3=r

Whenever I see code like this, it’s always a little tricky because you want to add the & at the end of each parameter except the last.  This always used to entail writing a special case in the loop to test if the index of the current element was the maximum index.  But with pattern matching and recursion there’s a much simpler and cleaner solution.  Like this:

defp add_params_to_url(url,[%{:name => name, :value => value}]) when is_binary(url) do     #1
 "#{url}#{name}=#{value}"
end
defp add_params_to_url(url,[%{:name => name, :value => value} | t]) when is_binary(url) do   #2
 url = "#{url}#{name}=#{value}&"
 add_params_to_url(url,t)
end
defp add_params_to_url(url,[]) when is_binary(url), do: url   #3

This is Elixir for those unfamiliar with it.  Basically it’s three function clauses.  The first clause (#1) is hit if only one element is in the list passed into the function. The second clause (#2) is hit if multiple elements are present in the list and the third clause (#3) is hit if the list is empty.

So this is how this works.  When I call add_params_to_url, Elixir will automatically try to match the correct function call dependent on which list I pass.  It will also stop at the first function clause which matches so that other function clauses will not be evaluated.

If I pass a list of URL params which has only one element, clause 1 is matched and the parameter and value are appended and I’m done.  The URL already has the ? on the end, of course.  If I pass a list of URL params with mutliple elements, clause 1 doesn’t match so Elixir jumps down to clause 2 and that matches.  Clause 2 takes the first element from the list tacks it on to the list of parameters with a & at the end and then recursively calls itself with the tail of the list.  If the tail of the list contains more than one parameter, clause  1 will once again fail to match and clause 2 will match again.  If it contains only one parameter, clause 1 is matched.  Because clause 1 doesn’t call itself recursively, clause 3 should never be matched; it’s actually more of a guard case in case someone calls the function with an empty parameter list by mistake.

This, to me, is a small bit of genius.  Much simpler to get exactly the effect I want, that is not having an extraneous character tacked to the end of the string, and it’s nice and simple.

By the way, it occurs to me that I might be able to use a reduce or a fold function to achieve this same effect.  The issue there is that it’s less apparent what it is that I’m trying to do and I also run into the same problem–that is, how do I deal with that last element in the list so I don’t get my separator appended?

Rebar3 Beta1 on Chocolatey NuGet

I had a need for the Erlang build tool rebar for a project I was trying to start on; a bit of pen testing via Elixir.  I was going to pull down the rebar3 script from the site and fix it up for myself and it occurred to me that others might want a way to get the script easily too.  So rather than just building something to work for myself, I took a little extra time and built a Chocolatey NuGet package for Rebar3-Beta1.

The package takes care of insuring you’ve got Erlang first although honestly I can’t imagine anyone interested in Rebar that wouldn’t already have Erlang on their machine.  It also takes care of setting up a shortcut for Rebar and putting it in the path.  And, of course, like everything else in CNG, it also handles uninstalling the tool if you decide you no longer want or need it.

For now the package is still awaiting moderation on CNG but please feel free to pull it down and give it a try.  Feedback is a gift and I hope some of you will share that gift with me.

Rebar3 on ChocolateyNuGet

Stupid Doc Tricks In Elixir

So last night we had our first Detroit Erlang/Elixir meetup and as part of it I wanted to do a little coding exercise to help people to get their feet wet with Erlang and/or Elixir, as they chose.  We simply worked through FizzBuzz and we came up with two different Elixir solutions and two different Erlang solutions. I never stop being surprised by developer creativity.

That said, I keep striving to improve the code I write and striving to use the tools that the language provides me.  Elixir has module attributes and it’s also got module documentation as a first class citizen in the language.  So I thought to myself why not extend my simple fizzbuzz code a bit to use these two features–to better learn how to use them.  Here’s the code such as it is:


defmodule FizzBuzz do
@fizz 3
@fizzmsg "Fizz"
@buzz 5
@buzzmsg "Buzz"

@moduledoc "
Ye olde FizzBuzz test in all of its glory.
If the number is a multiple of #{@fizz} then print #{@fizzmsg}.
If the number is a multiple of #{@buzz} then print #{@buzzmsg}.
If it's a multiple of both then print #{@fizzmsg<>@buzzmsg}.
Else print the number itself.

Example usage:
iex> for i <- 1..100, do: FizzBuzz.getFB(i)
1
2
#{@fizzmsg}
4
#{@buzzmsg}
"

  def getFB(n) do
    cond do
      rem(n,@fizz) == 0 and rem(n,@buzz) == 0 ->
        IO.puts @fizzmsg <> @buzzmsg
      rem(n,@fizz) == 0 ->
        IO.puts @fizzmsg
      rem(n,@buzz) == 0 ->
        IO.puts @buzzmsg
      true ->
        IO.puts "#{n}"
    end
  end
end

Now the code itself isn’t anything very special.  But the module attributes and the fact that I can avoid specifying magic numbers is just awesome.  What if I wanted to change the code to print “Argh!” on 3 instead of “Fizz”?  Of course were I to change the number for “Fizz” then I would need to make more extensive changes but this does cover one common type of change. With the code set up in this way, I only need to change things in one place and my docs will be updated as well as my code.

I know this is sort of a “Stupid Doc Trick” but it still seemed worth sharing with others.  The idea of only needing to change a constant in one place and having everything else update is a very appealing one.

A Naive Stack Implementation In Elixir

So one of the things I’ve done recently to help me to learn a new language is to tackle creating certain data structures and common operations on those structures in a given language.  And lately I’ve been digging Elixir quite a bit.  So I decided to tackle one of the easiest things I could tackle–a simple, naive stack implementation in Elixir.  First here’s the actual Elixir code:


defmodule Stack do

defstruct elements: []

def new, do: %Stack{}

def push(stack, element) do
 %Stack{stack | elements: [element | stack.elements]}
 end

def pop(%Stack{elements: []}), do: raise("Stack is empty!")
 def pop(%Stack{elements: [top | rest]}) do
 {top, %Stack{elements: rest}}
 end

def depth(%Stack{elements: elements}), do: length(elements)
 end

# Stack.new |> Stack.push(1) |> Stack.push(2) |> Stack.pop

First off, credit where credit’s due: this is more Saša Jurić’s code than it is mine.  I posted my initial code to Code Review and a few folks gave me some great suggestions on how to improve it. But his code seemed the best implementation so this is pretty much his code.

Looking at the code a bit closer, one thing long time OO folks will notice, and something that gave me a lot of trouble initially, is the fact that there’s no member variable to stash the stack in.  The stack has to be passed into each call and the new stack is returned.  This is a big leap in logic and even now after having played with functional for a few years it can still form a large stumbling block for me when I’m trying to solve a problem.

Another thing to notice is this line:


defstruct elements: []

This is within the scope of the module but what is it doing if there’s no member data associated with the module?  It’s easy to assume that modules are analogous to classes in OO and therefore it’s also easy to assume that elements is member data–but that would be a bad assumption.  Elements is actually an abstract data type closely associated with the Stack module.  It’s a way of specifying more information about the data that the various functions in Stack will work with.  You cannot access elements from outside of Stack and in fact it’s not private data within Stack.

One comment Saša made resonates for me. To paraphrase his point,  there is already a stack implementation in Elixir; it’s called a list.  So why bother to build another one?  It’s a fair question; my answer is that if I needed a stack, I’d rather see code that deals with “Stack” directly than see code that deals with lists and has comments littered all over the place that it’s using a list as a stack.  Of course, it’s syntactic sugar but at some level anything other than raw 1’s and 0’s is syntactic sugar.  It’s a question of making it easier for other developers to understand the intent of the code.

I share this not because it’s great or interesting code (although it was much improved by feedback from Johnny Winn, Saša and José Valim) but because someone may want to study this relatively simple code to learn more about Elixir.

 

 

 

New Version of Elixir Chocolatey Goodness

Paul Schoenfelder and I are sort of trying to get more Windows developers to take a look at Elixir.  We both think Elixir’s got a great story to tell and Windows developers will be very excited when they find out more about it.

In that spirit, we’ve updated the Chocolatey NuGet package for Elixir to the latest development release (v0.12.5).  This is just the first step in getting better support for Elixir on Windows–we’ve got more planned for the future.

Please feel free to grab that Chocolatey goodness and let us know if you run into any problems or if you’ve got suggestions.  We’ve set up a github organization and repository for our work; feel free to open an issue there or post something on the Elixir mailing list or post a comment here.

EDIT:

The Chocolatey NuGet Package is now up to v0.13.2 (as of May 12, 2014)