The Artima Developer Community
Sponsored Link

Weblogs Forum
Ruby vs. Groovy

8 replies on 1 page. Most recent reply: Mar 31, 2006 12:11 PM by Eric Armstrong

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 8 replies on 1 page
Eric Armstrong

Posts: 207
Nickname: cooltools
Registered: Apr, 2003

Ruby vs. Groovy (View in Weblogs)
Posted: Mar 19, 2006 7:38 PM
Reply to this message Reply
Summary
Ruby and Groovy are contrasted. Despite high hopes and best wishes for the Groovy project, in this author's eyes Ruby turns out to be the winner for most scripting tasks.
Advertisement

Preface

It has taken me quite a while to decide to share these thoughts. I really like the folks who are implementing Groovy. I found them to be extremely helpful on the mailing list, and I like their basic concept. A truly portable scripting language is a terrific idea. Unfortunately, that portability seems to be acquired at the expense of the two features that make scripting languages so seductive: Minimal coding and fast write/test/revise cycles.

On the other hand, even if Groovy eventually turns out to be terrific, it would still make sense to learn Ruby today--if only because so much has been written about it. That abundance makes it possible to become familiar with the strange new constructs like closures that are so unfamiliar to most Java hackers. So understandnig both Java and Ruby should make it possible to easily transition to Groovy, when it makes sense.

Comparing the Languages

I began looking at Groovy with high hopes and great expectations, but reluctantly had to conclude that it's going to be the technology of choice only in very limited set of use cases--primarily ones in which the VM is already running.

For general purpose scripting, the time it takes to crank up the VM and intitialize the interpreter is a deal killer--as much as 30 or 40 seconds on my machine. I get better performance compiling and testing Java code in an IDE, especially if it supports incremental compilation in a background task.

The start-up delay is sufficient by itself to rule out Groovy as a general purpose scripting language. But unfortunately, it gets worse:

  • Things are still in flux, to the point that many discussions on the user list are aimed at deciding how the language should be implemented. That's terrific, from the agile methodology perspective. It means that user needs are feeding into the design. But it also means that the basic language design is not yet complete.
  • Lack of documentation. It's to be expected at this stage of its evolution, but given that things haven't entirely settled down yet, it's pretty scary to contemplate using it for anything important.
  • Mostly unhelpful ANT integration. Ruby got this one right with Rake--super simple syntax plus the power of the language when you need it. Groovy has (so far) missed a serious opportunity here. You can call ANT tasks from a Groovy script, and you can invoke a Groovy shell from inside ANT, but neither one of those alternatives has anything like the expressive power or sheer convenience of Rake. (For more on Rake, see Martin Fowler's article at http://www.martinfowler.com/articles/rake.html)
  • Dependence on the Java library. It provides a lot of power, but utilizing those libraries means the language hasn't provided the kinds of one-line operations that make it easy to do the simple things you can do with Ruby--for example I/O and XML parsing. (For more, see Make, Mailing Lists, and Ruby at http://www.artima.com/weblogs/viewpost.jsp?thread=152464)
  • Ruby has some really cool features like modules and structs. Maybe Groovy does, too. It's hard to say, given the documentation. But more likely the requirement that compiled Groovy scripts must function as JVM classes will be a limiting factor in this area.
  • Then there are features inspired by Unix command shells--the ability to expand variables inside of a double-quoted string, and the ability to execute a shell command inside of back-quotes and get back the return string. Of course, shell commands are platform=dependent. But in Ruby the very definition of a method is determined at runtime, so it's possible to code multiple-platform versions with no significant overhead--because the conditional branch that determines how the method operates only occurs once, when the method is first read.
  • Rake may well be taking advantage of the dynamic behavior when it implements the kind of cross-platform commands you typically need in a shell script: Commands like cd, mkdir, and mkdir_p (to a make a directory from a path, and all directories that need to be made to get to it). To tell you the truth, I don't know any language intended for scripting can do without such things. (To my mind, those functions should be part of the standard library.)
  • And speaking of dynamic, runtime behavior, Ruby has lambda functions: the ability to generate code on the fly and execute it. Those turn out to be useful when defining Rake tasks, as Jim Weirich describes so nicely: http://onestepback.org/index.cgi/Tech/Ruby/EckelAndFowlerOnBuildSystems.rdoc http://onestepback.org/index.cgi/Tech/Rake/Tutorial/RakeTutorialAnotherCExample.red

Ruby sure isn't perfect. There are many Perlisms I'd rather not have seen, and it has too many ways to do things, imo. That flexibility is great when you're writing code, but it makes things harder when you're reading it, because you have to master the idioms favored by whoever did the writing. (You can alias things in Ruby and you can even overload operators--so you could conceivably write something that /nobody/ could read.)

Bottom Line

If you need a scripting language, Ruby is a great one.

When it comes to building an application with multiple authors and long term maintainability, I'd say there's a lot of decision-making to do before going with Ruby. If you're going agile with a small team that can easily teach each other its favorite idioms, Ruby will probably work. If you adhere to a more structured methodology and have a large, long term project with many lines of code--so you can expect a fair amount of turnover among the people who will be maintaining it--then Ruby probably isn't a good fit.

Once the problems of documentation and open design issues are resolved, Groovy may yet find a home in that sort of application-building environment. It will provide dynamic flexibility, like Ruby, but with full JVM integration so you can build and use Java classes.

But when we begin to drag in all that machinery, we're not talking about something that feels like a "scripting" language, anymore. We're talking about something that lies somewhere between a scripting language and an application programming language. So Groovy may yet find a home, but for the kind of fast development cycles I was looking for, Groovy simply isn't the language. At least not yet.

I still think that a truly portable dynamic scripting language is a great idea. I just don't see how it can be done in the JVM, except in some sort of server-side setting where the JVM is kept running and initialized, and there is some mechanism to feed it a script on the fly.

But to rapidly develop those scripts, an "on the fly" mechanism is needed for testing, as well. In other words, the JVM has to be effectively part of the operating system--wholly integrated into it so the startup time disappears. Until that's done, I don't see how Groovy can provide the same kind of immediacy that Ruby provides. The other problems can eventually be resolved. But that startup hurdle seems insurmountable in theory, as well as in practice.

Then again, maybe there are some viable usage scenarios I've overlooked. That would be nice.


Bruce Eckel

Posts: 875
Nickname: beckel
Registered: Jun, 2003

Re: Ruby vs. Groovy Posted: Mar 20, 2006 1:49 PM
Reply to this message Reply
A small nit or question:

>And speaking of dynamic, runtime behavior, Ruby has lambda functions: the ability to generate code on the fly and execute it.

Are you sure this is the definition of lambda functions? I ask because Python has a lambda, which is really a way to create an unnamed function, but it also has the ability to execute any piece of text via exec().

I suppose the question is also more complex in Ruby because when you make a block call you are basically passing it an unnamed function.

Eric Armstrong

Posts: 207
Nickname: cooltools
Registered: Apr, 2003

Re: Ruby vs. Groovy Posted: Mar 20, 2006 5:44 PM
Reply to this message Reply
The language claims the ability to dynamically generate and execute code, and lambda functions look to be the way that's happening in the Rake examples I've seen. But then I'm still learning my around the language, too...

Eric Armstrong

Posts: 207
Nickname: cooltools
Registered: Apr, 2003

Re: Ruby vs. Groovy Posted: Mar 21, 2006 5:49 AM
Reply to this message Reply
> The language claims the ability to dynamically generate
> and execute code, and lambda functions look to be the way
> that's happening...
>
Whoops. I was off base. You can generate code in a string and use *eval* to execute it. Since the language is ynamic, new methods can be generated that way, and then executed. (I've been reading more in The Ruby Way.)

The lambda keyword is a synonym for proc. It makes an object out of a block, which otherwise isn't really an object. It's not clear yet where that makes a difference, since blocks appear to be automatically converted to proc objects in most of the cases where you use one. (If that *isn't* happening, it's not clear what the difference is.)

Here, the block of code is not defined as an object:

list.each {|x| ...do something with list item...}

But whether it is, isn't, or gets converted to one, the result is the same: The block gets executed for each item in the list.

Using lambda or proc seems to give you a pointer to the block that you can pass around:

myMethod = lambda {|x| ...do something with an X...}

I haven't seen the use case that motivates that feature in an application, but the language seems to be using it a lot under the covers.

Then there are closures. So far, a closure looks like a block that takes advantage of its definition context. The Ruby Way gives this example of creating a closure using a proc:

def power(n)
proc {|base| base**n}
end

square = power(2)
cube = power(3)

a = square(4) # 16
...

Here, the power method returns the value of the last expression evaluated. In this case, it's a proc object, which can then be assigned to a variable like square.

But apparently, that's just one way to create a closure...and I'm still trying to come to grips with exactly what a closure is.

If I sound a little confused, it's only because I am. But I'm also excited. There is a lot of power here, with a lot of different ways to skin the cat, and things that share some similarities.

For example, we could have gotten the same effect by creating a string that looks like "#{base}**2" and then passing it to eval to calculate a square. For all I know, that's what Ruby is really doing internally. Or not...

Bottom line, the concepts behind eval, block, yield, proc/lambda, and closures appear to be the key to unlocking the power of Ruby's dynamic behavior--not to mention symbols (:x) and it's reflection mechanisms.

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Ruby vs. Groovy Posted: Mar 21, 2006 8:45 PM
Reply to this message Reply
Don't most dynamic languages have eval() and/or exec()? In addition to Ruby, Python and JavaScript/JScript have it.

Eric Armstrong

Posts: 207
Nickname: cooltools
Registered: Apr, 2003

Re: Ruby vs. Groovy Posted: Mar 21, 2006 9:30 PM
Reply to this message Reply
Matt wrote:
>
> Don't most dynamic languages have eval() and/or exec()?
> In addition to Ruby, Python and JavaScript/JScript have
> it.
>
Python probably does. I don't see how it work in Javascript, though. Being pretty much an "old school" guy, I have a lot of coming up to speed to do on (what to me are) the newer dynamic features. I mean, I've hacked Forth, but there wasn't a lot of eval'ing going on. And I played with Lisp in grad school, but never got into deeply enough for those kinds of behaviors to become second nature.

So those are the "big things" for me, because they're the new ones that will give me expanded scope and power. For other important features, see my previous post: "Make, Mail, and Ruby". What's left is stuff I'm pretty familiar with--it's just a matter of finding out how the APIs work.

That said, I continue to be impressed with how few lines of code it takes to get things done in Ruby. That's practically the definition of fun.

Dirk Detering

Posts: 1
Nickname: ddet
Registered: Mar, 2006

Re: Ruby vs. Groovy Posted: Mar 22, 2006 6:03 AM
Reply to this message Reply
Groovy is interesting in our Java project exactly because it integrates tightly with the JVM and our application. Was no problem to get permission to use Groovy, as it is a Java lib/app. Reuse and glueing of all of our Java stuff is really a valuable part.

But personally I am a Ruby fan and prefer using that for my different scripting tasks on my workstation and at home, even up to somewhat bigger sized apps. I can create solutions very quick and reliable and sometimes deploy them as exe-files to where it is needed. I'm impressed by the possibilities of Mixins, by Rake, ERb and other very clear and smart stuff written in Ruby. So I can understand your arguments.

Unfortunately the lambda example you gave is exactly the point where Groovy does indeed better than Ruby:

def power(n)
proc {|base| base**n}
end

square = power(2)
cube = power(3)

a = square(4)
puts a # => 16


This example is one to one translatable to Groovy:

def power(n) {
{ base -> base**n }
}

square = power(2)
cube = power(3)

a = square(4)
println a // => 16


But regarding a more functional way of programming, you should have a look at this example, especially with your former LISP experience:

A typical currying example in Groovy:

add = { x -> { y -> x + y }}
println add(3)(4)


And its pendant in Ruby:

add = proc{ |x| proc{ |y| x + y }}
puts add.call(3).call(4)


The difference is that you have to explicitly use the 'proc' or 'lambda' keyword to create a closure and to explicitly call 'call' to execute it, what makes it a bit less handy in Ruby.

Or to turn it: Block-Closures in Groovy are the main benefit in my eyes compared to Java and I use it very often.

Then there are closures. So far, a closure looks like a block that takes advantage of its definition context.

Exactly. A block is an autonomous piece of code. The reference to variables in its definition context makes it a closure.
Thus, even in Java there are closures: inner class instances returned by an outer class instance, referring to that outer class instance's private features. (See "Thinking in Java")

stephan schmidt

Posts: 1
Nickname: m00
Registered: Mar, 2006

Re: Ruby vs. Groovy Posted: Mar 29, 2006 6:31 AM
Reply to this message Reply
Ruby is a very clean, nice, powerfull language with a very low noise level, but still excellent readability. I really like it.

The problem with Ruby is not the language. The problem is no or Japanese library documentation, C dependencies which make it hard to install some ruby libraries (like SVN bindings) and the low number of libraries. Whenever I start a bigger project in Ruby, after some time I usually run in one or more of these problems.

Working inside Rails is great. Once you need to interface with something outside of Rails, your path gets very rough.

But the main difference between Ruby and Groovy is afaik the fact that Ruby is dynamically reference typed and Groovy is both dynamically and statically reference typed.

I wrote more on this difference: http://blog.reposita.org/?p=4

bye
-stephan

Eric Armstrong

Posts: 207
Nickname: cooltools
Registered: Apr, 2003

Re: Ruby vs. Groovy Posted: Mar 31, 2006 12:11 PM
Reply to this message Reply
Stephan Schmidt wrote:
>
> Working inside Rails is great. Once you need to interface
> with something outside of Rails, your path gets very
> rough.
>
> But the main difference between Ruby and Groovy is afaik
> the fact that Ruby is dynamically reference typed and
> Groovy is both dynamically and statically reference
> typed.
>
> I wrote more on this difference:
> http://blog.reposita.org/?p=4
>
Great points. I appreciate your comments. And that writeup is definitely worth a read. It very nicely explains the different things that "dynamic" can mean, with some tremendous examples.

Flat View: This topic has 8 replies on 1 page
Topic: RESTful and User-Friendly URLs Previous Topic   Next Topic Topic: Think from the User In

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use