Wednesday, June 10, 2009

Erlang Riddle for Rubists

The next "Erlang made stupid simple for Ruby programmers" post & screencast is in the making. I am reading again and again the pages of Software for a Concurrent World and try to synthesize Erlang's essence for the "average" Rubist.

Some stuff is straight forward, like Funs which is the Erlang Funny name for Anonymous functions.

ERLANG:

1> Z = fun(X) -> 2*X end.
#Fun
2> Z(2).
4
3> Double = Z.
#Fun
4> Double(4).
8
5> Double(4).
8

RUBY:

irb(main):004:0> Z = Proc.new { |x| x*2 }
=> #
irb(main):005:0> Z.call(2)
=> 4
irb(main):006:0> Double = Z
=> #
irb(main):007:0> Double.call(2)
=> 4

Great stuff, never had to use it in Ruby - but maybe in Erlang it might serve me, who knows....

Now that is an easy one. Later in the book, Joe Armstrong gives an example of a function that returns all permutations of a given string.

perms([]) -> [[]];
perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])].

I have tried to rewrite it in Ruby, in a form that would mostly imitate what's done here.
That's my best try so far:

def prem(s,nx = [])
return nx.join if s.empty?
s.collect { |b| prem(s-[b],nx+[b]) }.flatten
end

puts prem('dor'.split(//))

output:

dor
dro
odr
ord
rdo
rod

I hate the flatten hack I did there to simulate Erlang's valuse return as one Array.
I dislike having to send prem all his recursive "past" (as "nx").

I think there must be a better way to do it. A better way that will deliver the Erlangian concepts.
Do you think you might have a better way to pronounce the Erlangian magic of this function in Rubish ? If so, please post it here (as a comment) I'd really love to see it!

Whoever has a better solution (me need to like) will get full credits and endless honor (!)

2 comments:

Anonymous said...

Hi Dor, Just perusing your site, everything well "laid out", I suppose thats your technical mindset will be back in a while to soak up the Techno/feel.....PAX

dor kalev said...

I just gave this question in an interview and came up with a new shining answer myself.
I can't say its quicker or prettier but I enjoyed a new solution after never getting one from my dedicated readers ;-)

def permutations_party(k)
(0..(k.size**k.size)-1).map do |x|
y = x.to_s(k.size).rjust(k.size,'0').split(//)
y.map { |x| k[x.to_i,1] }.to_s if y.uniq.size == y.size
end.compact
end

Post a Comment