A big smile appeared on my face tonight after typing the following:

-module(math1).
-export([factorial/1]).

factorial(0) -> 1;
factorial(N) -> N * factorial(N-1).
def factorial(n)
  return 1 if n == 0
  n * factorial(n-1)
end

Maybe not so obvious. But check this out:

-module(temp).
-export([convert/2]).

convert({fahrenheit, Temp}, celsius) ->
        {celsius, 5 * (Temp -32) / 9};
convert({celsius, Temp}, fahrenheit) ->
        {fahrenheit, 32 + Temp * 9 / 5};
convert({reaumur, Temp}, celsius) ->
        {celsius, 10 * Temp / 8};
convert({celsius, Temp}, reaumur) ->
        {reaumur, 8 * Temp / 10};
convert({X, _}, Y) ->
        {cannot,convert,X,to,Y}.

This a simple temperature conversion program. Done in Ruby with methods, although not normally the way that I would introduce such functionality into a program:

def convert(from, temp, to)
  case to
    when :celsius     : to_celsius(from, temp)
    when :fahrenheit  : to_fahrenheit(from, temp)
    when :reaumur     : to_reaumur(from, temp)
    else                "cannot convert #{from} to #{to}"
  end
end

def to_celsius(from, temp)
  case from
    when :fahrenheit  : 5.0 * (temp - 32.0) / 9.0
    when :reaumur     : 10.0 * temp / 8.0
    when :celsius     : temp
    else                "cannot convert #{from} to celsius"
  end
end

def to_fahrenheit(from, temp)
  case from
    when :celsius     : 32.0 + temp * 9.0 / 5.0
    when :fahrenheit  : temp
    else                "cannot convert #{from} to fahrenheit"
  end
end

def to_reaumur(from, temp)
  case from
    when :celsius     : 8.0 * temp / 10.0
    when :reaumur     : temp
    else                "cannot convert #{from} to reamur"
  end
end

Yikes! The pattern matching in Erlang functions really comes in handy. Here is the output from both terminals (Erlang then Ruby):

justinmbp:~ justin$ erl
Erlang (BEAM) emulator version 5.5 [source] [async-threads:0]

Eshell V5.5  (abort with ^G)
1> c(temp).
{ok,temp}
2> temp:convert({fahrenheit, 98.6}, celsius).
{celsius,37.0000}
3> temp:convert({reaumur, 80}, celsius).
{celsius,100.000}
4> temp:convert({reaumur, 80}, fahrenheit).
{cannot,convert,reaumur,to,fahrenheit}
5> temp:convert({celsius, 37}, fahrenheit).
{fahrenheit,98.6000}
6> temp:convert({celsius, 100}, reaumur).
{reaumur,80.0000}
7>
justinmbp:~ justin$ irb
irb(main):001:0> require 'temp'
=> true
irb(main):002:0> convert(:fahrenheit, 98.6, :celsius)
=> 37.0
irb(main):003:0> convert(:reaumur, 80, :celsius)
=> 100.0
irb(main):004:0> convert(:reaumur, 80, :fahrenheit)
=> "cannot convert reaumur to fahrenheit"
irb(main):005:0> convert(:celsius, 37, :fahrenheit)
=> 98.6
irb(main):006:0> convert(:celsius, 100, :reaumur)
=> 80.0
irb(main):007:0>

And I’m still leaving out the fact that Erlang is returning a Tuple that includes what type of data to work with. With Ruby, it’s a simple Fixnum. I suppose I could have used a Hash to store that information in the return value, but … this was suppose to be a simple little example that turned into something a little larger than I expected.

For a more fair look at the Ruby code, here is how I would have normally structured temperature conversion functionality:

module Temp
  class Fahrenheit
    attr_accessor :temp

    def initialize(temp=0)
      @temp = temp
    end

    def to_celsius
      5.0 * (@temp - 32.0) / 9.0
    end
  end

  class Celsius
    attr_accessor :temp

    def initialize(temp=0)
      @temp = temp
    end

    def to_fahrenheit
      32.0 + @temp * 9.0 / 5.0
    end

    def to_reaumur
      8.0 * @temp / 10.0
    end
  end

  class Reaumur
    attr_accessor :temp

    def initialize(temp=0)
      @temp = temp
    end

    def to_celsius
      10.0 * @temp / 8.0
    end
  end
end

While it’s not really the same and I am comparing apples to oranges, I still find it very interesting. This is my first foray into a functional language. I’m currently reading Concurrent Programming in Erlang and hope to be in to some of the application code by the end of the weekend.

After taking some good notes, hopefully I’ll be able to re-create in Erlang a light message queuing/routing system I wrote in Ruby this week.