Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Friday, April 20, 2007

From C to Java to Ruby

I was having this casual conversation with a colleague about Ruby who isn’t using Ruby and I was selling him the elegance of Ruby and all that.
I said – “Remember the feeling when you moved from C development to Java? It felt like you have shed several pounds of weight attached to your shoes and you can now walk light. It is the same Deja Vu when you start to use Ruby coming from Java world.”

Then later when I was at my desk I thought of a better analogy.

  • Working with C was like using an Axe, cutting away at a tree trunk. Powerful but tiring and you run the risk of missing the tree and getting your toe.

  • Working with Java was like throwing away the Axe but getting a nice hack saw. It was controlled and safe. A little slow but easy to work with.

  • But working with saw can be boring monotonous repetitive work. So come in Ruby. Ruby is like a Swiss army knife. Elegant, beautiful, small, doesn’t require you to wrestle with it, can be different things at different times but as the runtimes of today, much slower than Java. You may not be able to cut a tree but can carve beautiful motifs out of it.

Wednesday, March 28, 2007

Calculate once Cache forever

In the pickaxe book there is a section which talks about the use case of a "once" directive. So you have a method with complex calculations and you want to be able to cache the result.
One "clunky" technique mentioned there is to store the result in an instance variable and check it before doing the calculation.

def as_string
unless @string
# complex calculation
@string = result
end
@string
end

The book then introduces Tadayoshi Funaba's once directive implementation.

def once(*ids)
for id in ids
module_eval <<-"end;"
alias_method :__#{id.to_i}__, :#{id.to_s}
def #{id.to_s}(*args, &block) (@__#{id.to_i}__ ||=
[__#{id.to_i}__(*args, &amp;block)])[0]
end
end;
end
end

(For details please look at Funaba San's once )

There is a related technique that I wanted to talk about. This is slightly different in semantics as it rewrites the method itself and though cannot be a substitute for the once directive but could be used in this or similar situations.
Let's look at the code first.

class Test
def calc
# complex calculation
@result = "result"
puts "Whew! Here is the result"
if @result
def self.calc
puts "No sweat!"
@result
end
end
@result
end
end

What is happening here is that when the class is evaluated the outer method calc() is defined, but when the method calc() is executed, conditionally the singleton method calc() is defined on the object. The "self" here would refer to the object of the class Test in whose context the outer method calc() is executed. The end result is that we get a singleton method.

irb(main):077:0> t1 = Test.new
=> #
irb(main):078:0> t1.calc
Whew! Here is the result
=> "result"
irb(main):079:0> t1.calc
No sweat!
=> "result"

irb(main):084:0> t2 = Test.new
=> #
irb(main):085:0> t2.calc
Whew! Here is the result
=> "result"
irb(main):086:0> t2.calc
No sweat!
=> "result"

This can be used to conditionally re-define the behavior of a class on an object by object basis and so has a more general purpose use than just result caching.

Tuesday, March 27, 2007

How do you swap variables?

At least some 10 years ago someone asked me this question in an interview - "How do you swap two variables without using a temporary variable"
I now vaguely remember how I answered the question then but I know I did *not* use XOR in that answer, I did not know it at that time but its really very cool.


x = x ^ y
y = x ^ y
x = x ^ y


But of course in Ruby you would just do


a,b = b,a

and thats it! Have a nice day. May I help the next customer in line?

This is Ruby parallel assignment in action which has several cool uses but begins to really shine when you splat and unsplat.

Sunday, March 25, 2007

What's with type safety, ducks are a type that don't bite

Last week I was at SD West conference in Santa Clara and attended some talks on Ruby. In one of them by Joe O’ Brien someone asked about the comparison of static v/s dynamic typed language. This perhaps is one of the most common debate that occurs when you have a room full of Ruby and Java developers with an even split.

I will not go into the details of what transpired there but as you can imagine it was as much religious as technical.

I have coded in many languages and have been on both sides of the argument at different times. After 9 years of Java I had this thought ingrained in my mind -

Compiler is my friend. Static typing saves the day (and night) and dynamic typing is either for those frivolous javascripty web coders or for the not so serious fringe scriptable use cases

After almost 6 months with Ruby I am a changed man. In fact now that I look back I feel like a child who just feared venturing in dark, imagining ghosts where there were none.

Static typing is so overrated. Dynamic typing opens a whole world of possibilities hitherto locked out by inflexible attitude.

Here is a Java snippet


public class Type {
public static void main(String args[]) {
for(int i=1, x=3; i<30; i++)
x *= 3;
System.out.println(x);
if (x<0)
System.out.println("I'm so busted");
System.exit(-1);
}
}
}
}

And here is some Ruby code -


x = 3
30.times do
puts "#{x} #{@y = x.class if @y != x.class}"
x *= 3
end

Now decide for yourself which of these is "safer".