Thursday, March 24, 2011

Example of the difference between Ruby and Java

Having worked extensively with both ruby and java, I thought I'd share some interesting differences between how one can approach solving problems in the two languages.

Let's take a common example of a function that will take a variable number of arguments and return a string with all non-null values separated by commas. We'll start by just using the core runtime and see what we can do.

Here's the Java example:
public class StringJava {
    public static void main(String[] args){
        System.out.println(printComma("test1","test2","Test3"));
        System.out.println(printComma("test1",null,"Test3","Test4"));
    }
    public static String printComma(String... names) {
        StringBuffer buff = new StringBuffer();
        boolean first = true;
        for (String str: names) {
            if (str != null) {
               if (first) {
                   buff.append(str);
                   first = false;
               } else {
                   buff.append(','+str);
               }
            }
        }
        return buff.toString();
    }
}

Now the equivalent in Ruby:
def print_comma(*data)
  data.compact.join(',')
end
puts print_comma "Test1","Test2","Test3"
puts print_comma "Test1",nil,"Test3","Test4"


Ouch! It actually gets much better, because if you really need this sort of functionality a lot,you could just add the method directly to the Array class and do this in ruby:

class Array
  def comma_join
    self.compact.join(',')
  end
end

puts ["Test1","Test2","Test3"].comma_join
puts ["Test1",nil,"Test3","Test4"].comma_join


The latter approach would simply be impossible in java, but with just a little extra effort, allows you to enhance your ruby Array class to give you some very useful functionality.

At it's core, ruby is geared toward rapidly producing compact code and enables developers to modify their environment to support just about anything they want to do. Java, on the other hand, is geared more toward following a lowest common denominator standard at the expense of being more verbose and not allow developers to expand the language to meet their needs.

I'm not suggesting ruby is superior in all cases, but from a flexibility and development effort perspective, there really isn't any fair comparison, ruby trounces java in almost every respect.

14 comments:

Anonymous said...

Yes it clearly shows why Java sucks. You've taken one of those problems real programmers struggle with like every minute and made an example of it!

I wish there was an easier way in Java to master the common example of taking a variable number of arguments and returning a string with all non-null values separated by commas! It might come in handy, one day!

Anonymous said...

I'd have to argue against what you've said. Ruby is a dynamically-typed language so it's much easier to run into runtime errors (in fact, ALL of your errors WILL be runtime errors). Ruby and other dynamic languages give up the static type-checking safety of compiled languages. Your comparison is shallow at best.

Anonymous said...

And now make the Ruby example as efficient (both in time an memory) as the Java one. Hint: you'll end up with almost the same number of lines ;)

Anonymous said...

In PHP:
function print_comma($array) {
return implode("," $array);
}
echo print_comma(array("Test1","Test2","Test3"));
echo print_comma(array("Test1",null,"Test3","Test4"));

Anonymous said...

You can simply write your own 'join' function or use an existing one:
import org.apache.commons.lang.StringUtils;
StringUtils.join(names, ',');

But why do you compare Ruby with Java? It makes more sense to compare Ruby with Python, Perl, Groovy...

Anonymous said...

in C#

string.Join(",", new string[] { "Test1", "Test2", "Test3" });

Anonymous said...

C# - small correction
Console.Write(string.Join(",", new string[] { "Test1", "Test2", "Test3" }));

Anonymous said...

its not about the language, its about your skills in that language....

me said...

One thing I've noticed is that other languages like PHP and C# seem to have also solved this problem. I wonder why java hasn't?

v-tek said...

A few months back Expensify did a big spiel on .NET based programmers not being real programmers because of the degree of abstraction innate to the platform. Now you mention one specific abstraction in Ruby as evidence of its superiority. I code them all, I prefer PHP (also loosely typed), and I think Rails is probably the most abstracted platform of all I have used. Abstraction is great when we talk about split and join, but installing gems and using other people's code in products you put your name on is dangerous. A real coder can build the methods he needs and the trade-offs are often enormous. In the case of Java it's entirely trivial (as your first commenter sarcastically demonstrated) to include a join method and if you'd like extend a native class to include it.

Developing your own library of tools should be compulsory to reach intermediate programmer. Senior programmers, we don't even need our libraries because we can code them ad-hoc with our right hand while our left hand is moving on to through the app logic.

-------
Another IT Blog

Anonymous said...

I like advanced functional features of a language but dislike dynamic runtime errors. Its a balance. Coding ease with static type and error checking mean that I use DotNet and C# most of the time.
Try this in other platforms and aim for bulletproof runtime i.e WILL Not Throw Errors at RUNTIME.
string joinnedononnullstartwithF = string.Join(",", (from s in new[]{"First","Second","F string"} where !string.IsNullOrEmpty(s) && s.StartsWith("F") select s).ToArray())

boomhauer said...

let's see a .net LINQ example!

Anonymous said...

LINQ example:

void Main()
{
Console.WriteLine(string.Join(",", names.Where(n => n != null)));
}


For your second Ruby example, C# equivalent is:

static class Extensions
{
public static string CommaJoin(this IEnumerable<string> names)
{
return string.Join(",", names.Where(n => n != null));
}
}

void Main()
{
Console.WriteLine(new [] {"Test1", null, "Test3", "Test4"}.CommaJoin());
}

I usually have an StringJoin() extension method on IEnumerable<string>, so I can do this:

new[] {"test1", null, "Test3"}.Where(n => n != null).StringJoin(",");

shobnaamkoly said...

Hi, this is very useful and learning lot form it.

Thanks for sharing.