More fun with Erlang

I am working on a prototype of an application that needs to proxy client HTTP requests to different origins. I needed a function that will filter HTTP headers before I forward them. Application is in Erlang, but since I’ve been a big Ruby fan for a while now… Here is a comparison of possible implementations:

Ruby:

  NO_FORWARD = ['Host', 'Content-Length', 'Accept-Encoding']
  
  def filter_headers(headers)
      headers.inject({}) do |result, (name, value)|
         result[name.to_s] = value unless NO_FORWARD.include?(name.to_s)
         result
      end
  end

Now, same code … but in Erlang:


filter_headers(Headers) ->
NoForward = ['Host', 'Content-Length', 'Accept-Encoding'],

Pred = fun({Name, Value}, L) ->
case lists:member(Name, NoForward) of
false ->
Key = case is_atom(Name) of
true -> atom_to_list(Name);
false -> Name
end,
[{Key, Value} | L];
true -> L
end
end,

lists:foldl(Pred, [], Headers).

I think given a bit more effort, each code sample might be even more compact, but even what I have looks pretty readable 🙂

Erlang – elegant, but mind blowing :)

I’ve been playing around with Erlang for a while now. Interesting thing about Erlang is that the language is pretty small and very consistent, I guess it is typical for functional language 🙂 , but in a same time it takes a long time to start thinking in “Erlang way”. Everything is based on pattern matching – function signatures, case and if statements are all just pattern matching. Once you get a hold of it… it is a lot of fun and makes code pretty clean, short and readable.
Here is an example of function that parses ttl – 20s, 10m, 2h :

first we have an entry point:


parse(Ttl) -> parse_ttl(lists:reverse(Ttl)).

And here comes all the fun :


%% Private Functions.

parse_ttl([$s | Ttl]) -> list_to_integer(lists:reverse(Ttl));
parse_ttl([$S | Ttl]) -> parse_ttl([$s | Ttl]);

parse_ttl([$m | Ttl]) -> 60 * list_to_integer(lists:reverse(Ttl));
parse_ttl([$M | Ttl]) -> parse_ttl([$m | Ttl]);

parse_ttl([$h | Ttl]) -> 60* 60 * list_to_integer(lists:reverse(Ttl));
parse_ttl([$H | Ttl]) -> parse_ttl([$h | Ttl]);

parse_ttl(_) -> false.

Since strings in Erlang are just lists of integers, it is very common to apply list functions to strings. The [H | T] notation allows you to separate “head” and a “tail” of the list; in our case first symbol and the rest of the string. And since we have reversed our original string before applying our pattern … it is working pretty well 🙂

Easy Helpers for Sinatra

I am spending more time with Sinatra apps. I think it is a perfect framework to start application with. What I like about Sinatra the most is how easy it is to extend it. Recently I was building a small app, that processes user provided templates and was looking for an easy way to add template components (helpers) to give customers a sort of DSL to work with. What I ended up doing was the following:

 
module Components
  
  components_path = File.expand_path(File.dirname(__FILE__) + '/components')

  files = Dir.new(components_path).select{|f| f =~ /.*\.rb/ } || []
  files.each do |f|
    body = File.new(File.join([components_path, f])).read
    name = File.basename(f, '.rb').capitalize + "Helper"
    module_eval <<-"end;"
      module #{name}
        #{body}
      end  
    end;
    Sinatra.helpers(const_get(name))
  end

end

Link to the file: http://gist.github.com/141220

As you can see this pretty simple Ruby magic allows me to put my “components” into a subdirectory and add them all as Sinatra helpers. Since the body of the component is wrapped into a module, component development becomes very easy. Following code, once saved into components directory will add a search helper to your app:

def search(options = {})
......
end

Pretty simple, but still fun 🙂