I haven't actually used Groovy much since, oh, egads, umh, 2004. It was at 1.0b6 and was taking a direction which I both disagreed with and found kind of boring. It was throwing away large chunks of dynamicity for some performance gains as it decided it really wanted to be compiled, after all. Large chunks of the new syntax I also disagreed with so... I wandered away, wishing everyone luck.
Well, funny things can happen in, er, three and a half years, so when a coworker suggested we look at Groovy for solving a problem my initial reaction was "erk, umh, I kind of like our use of JRuby for that" but Groovy wasn't even at 1.0 when last I used it, so it was a pretty unfair reaction. Looking again, it is at 1.5.4! Time to revisit!
After noting that none of my old code parsed, I worked through the tutorial. This isn't the same language I last used. It smells like Perl or PHP more than Ruby, which it rather resembled back then. Overall, my second "first" impression: totally practical, rather ornery. Will dig into it more.
0 writebacks [/src/groovy] permanent link
Tue, 02 Jan 2007Congrats! I fell out of the Groovy camp when I tried to stop doing anything JSR related on my own time, but I love the Groovy guys, and am super-excited for them! Groovy 1.0 is out!
0 writebacks [/src/groovy] permanent link
Thu, 11 Aug 2005MrG gets interviewed. I cannot stress enough how good Guillaume has been for Groovy. He's really stepped up over the last year. Go Guru G! Now if we can just get him to grow a beard...
0 writebacks [/src/groovy] permanent link
Sun, 16 Jan 2005
Re: Groovy Closures and Related Syntax Issues
Mike Spille has been putting his money where his mouth is in regards to Groovy, and it is definately a good thing to get good feedback =)
I want to expand on something which he touches on, but then munges up with another concept -- closures and anonymous functions. Closures are *lexical* in nature. A closure is a closure over a lexical scope. Lexical scope is the text of the program, not the stack it is evaluating in. Mike's explanation describes lexical scope more along the lines of dynamic scope (which is a whole other beast, only commonly encountered in elisp) intersecting with lexical scope. Mike explains the concept well, but then forgoes picking on Groovy for ramming the the two together when talking about them, and accepts them as is. Maybe Mike is nicer than me in that regard, I'm am going to pick a nit in this regard and seperate them.
You can achieve (limited) lexical closures in in Java using anonymous inner classes. Swing's event model is predicated upon them, even. Take the following:
final Object flag = new Object();
final int[] jobs_queued = { 0 };
for (int i = 0; i < job_count; ++i) {
Job job = new Job(new Runnable() {
publc void run() {
doSomethingLongAndAnnoying();
jobs_queued[0]--;
synchronized (flag) {
flag.notify();
}
}
});
for (;;) {
try {
executor.execute(job);
jobs_queued[0]++;
break;
} catch (InterruptedException e) {}
}
}
blockUntilCompleted(jobs_queued, flag);
The above code creates a Job and passes it to some asynchronous executor (actually using Doug Lea's util.concurrent package, with its InterruptedExceptions =) Now, this job takes as an argument an instance of Runnable
, in this case implemented as an anonymous inner class. The scope of the run
method in this Runnable
encloses the scope in which it is defined. It accesses and even modifies variables (final ones, anyway) in the local scope of the method body in which it is defined (jobs_queued
).
Now, note that this runnable is going to be executed in a seperate thread, in a different stack, and will still modify items in this scope. The scope of the run method encloses the scope in which it was defined.
Where closures get really interesting is in defining anonymous functions -- something that Lisp, Python, Ruby, Groovy, C#, etc all make really easy, and Java doesn't allow (anonymous classes with a single method yes, just the function, no). This is where you get into functional programming styles, which Java allows for, but not in a syntactically pleasent way (like doing objects C -- there are multiple ways of doing it, but none are really as nice as languages with a syntax designed to make it nice (Java, for instance)).
A lot of groovy's anonymous function (called closures in groovy space, something which needs to be changed imho) syntactic sugar stems from emulating the awesome power of Ruby's blocks while not having the block concept. Mike rails at some of the language oddities introduced by having all blocks be anonymous functions, rather than just be blocks. Ruby's blocks are not anonymous functions when created:
irb(main):001:0> foo = { puts "hello world" }
SyntaxError: compile error
(irb):1: syntax error
foo = { puts "hello world" }
^
(irb):1: syntax error
from (irb):1
irb(main):002:0>
But they can be used to create anonymous functions very easily:
irb(main):004:0> foo = proc { puts "hello world" }
=> #
irb(main):005:0> foo.call
hello world
=> nil
irb(main):006:0>
Blocks are their own thing in Ruby, and are used all over the place. The most visible is as a special argument to a function different from other arguments:
irb(main):011:0> 5.times { |i| puts i }
0
1
2
3
4
=> 5
irb(main):012:0>
Interestingly, the block, { |i| puts i }
is not an argument to the times
call. It is a block passed in, as can be seen most easily by looking at the error message if you skip it:
irb(main):012:0> 5.times
LocalJumpError: no block given
from (irb):12:in `times'
from (irb):12
from :0
irb(main):013:0>
Ruby allows the passing of a block to any function, the function may or may not *do* anything with it. It is a special argument which can be passed. This may seem like a bizarre special case, but it is actually wonderful when used in practice (it probably drives python people nuts, though, as it is too pragmatic ;-)
Now, Ruby and Groovy share a lot of similarities, and having the concept of blocks is one of them, though they implement it quite differently, and that makes for some semantic differences as well. Groovy does not have any kind of implied block parameter to functions, you must explicitely declare passed blocks as a param (though you don't need the &foo
"this is a function" stuff). A bare block is a valid expression which returns an anonymous function.
This may be nice, and is certainly a but easier to digest as there is a definate stumble when people start writing functions in Ruby which accept blocks (wait, I yield
to invoke it? huh?). It feels natural when you get it, but maybe that is because you just accept it, and passing a block as a formal param seems reasonable (though it is tricky as for syntactic nicety you want it to be last, but if you have a variable number of args, deciding if it is the final arg, or a block is... ick -- I do like Matz's solution, but it certainly is not the only way).
Groovy is strongly object oriented, but it is also strongly functional. It really encourages you to pass functions around -- and makes it easy to munge scopes. Building a lot of the core language syntax around support for this is a design decision, and a decision I have actively supported in the past, and will continue to in the future. It is good design, even if it is different from Java. You certainly don't have to use it, but it allows for much more expressive (expressive != terse) programs, and that is very good.
2 writebacks [/src/groovy] permanent link
Sun, 14 Nov 2004
Embedding Groovy Eval in Derby =)
Sitting in the Dervy tutorial at ApacheCon this morning decided to focus on something else for a a bit...
ij> select count(*), groovyEval('foo = ["woof", "meow"]; foo.join(" -- ") ') from fortunes;
1 |2
--------------------------
13686 |woof -- meow
1 row selected
ij>
Fun fun!
0 writebacks [/src/groovy] permanent link
Thu, 22 Jul 2004
<jstrachan> brianm: some code should arrive soon in groovy where we can
auto-download jars & dependencies from maven repos based on class loaders
<jstrachan> philip milne (ex-sun) has done it & plugged it into groovy
<jstrachan> so you can do things like
<jstrachan> new com.foo.Whatnot().doSomething()
<jstrachan> and it'll load the latest version of whatnot.jar from maven & add it &
dependencies to your classpath & run it
<brianm> hahahahahahaha
<jstrachan> would make scripting & using other libraries/frameworks really easy
<jstrachan> :)
<brianm> remote classlaoader pointed at jar in repo baby
<brianm> why download?
0 writebacks [/src/groovy] permanent link
Sat, 17 Jul 2004Just packaged up an rpm for Groovy 1.0b6 for you rpm-using people. It was built against Redhat ES3, but should work for any linux flavor with /etc/profile.d/
Have fun!
0 writebacks [/src/groovy] permanent link
Wed, 05 May 2004While waiting for the 2 gigs of WoW beta to download I whipped up a little game to entertain myself using the wonderful NanoWeb. NanoWeb is great. It makes actions in webapps almost fun!
Go play if you have some time to kill =) Take a peek at how simple the whole thing is as well :-)
2 writebacks [/src/groovy] permanent link
Tue, 04 May 20045:58:[Guillaume] Guillaume 5:58:[GroovyBot] Guillaume is a groovy despot 5:58:[Guillaume] jstrachan 5:58:[GroovyBot] James is groovy's father 5:59:[Guillaume] LOL :-)))) 5:59:[Guillaume] I feel like a kid playing alone with his new toy 5:59:[markcc] Hi Guillaume. What's a groovy despot? 5:59:[GroovyBot] Guillaume is a groovy despot 5:59:[Guillaume] LOL ;-) that works
It's just fun =)
0 writebacks [/src/groovy] permanent link
Mon, 03 May 2004
New Syntax Definition for Groovy in SubEthaEdit
Marshall Elfstrand (thank you!) cleaned up the Groovy syntax defintion file for SubEthaEdit which I posted a while back. He took out a bunch of the Rubyisms and put in the fancy Groovy stuff =) Anyway, download it, and copy it into ~/Library/Application Support/SubEthaEdit/Syntax Definitions/
and you should be good to go. You will need to restart SubEthaEdit after copying it over if you want it to be picked up.
0 writebacks [/src/groovy] permanent link
Thu, 25 Mar 2004Wrote a fun little groovy script earlier today to copy IMAP messages to Exchange. JavaMail and Groovy made this pretty simple, so simple I had to do a bit of gold plating. Oh well =)
The fun part is in this snippet:
traverse = { folder, operation |
traverse_subfolders = { folder, operation |
recur = this
folder.list().each {
operation(it)
recur(it, operation)
}
}
operation(folder)
traverse_subfolders(folder, operation)
}
Groovy suffers from a cannot-call-closure-by-name-from-itself problem. Because the closure is a first class object though, you have access to it via this
, so you can, in fact, recur on your closure.
0 writebacks [/src/groovy] permanent link
Thu, 18 Mar 2004
Get it Right -- Groovy is Endorsing the JCP
Lots of the excitement around the Groovy JSR points to the idea that James et. al. are trying to use the JCP to rubber stamp groovy as the one-true-scripting-language. This is absurd, in my opinion, but I understand the fears.
The more interesting point is that this endorses the JCP as a standards body (not that it needs endorsement) and shows faith in the JCP's ability to grow a standard that is more than a language extension. Most people seem to frown at ECMA and ISO for standardization of languages -- look at C# and ECMA. Who believes that anyone besides MS can make changes to the C# spec, or that anyone who provides a real threat to MS won't get sued into oblivion despite the existance of a standard (you still need to be able to afford five years of good lawyers in court to defend yourself)?
There is a key point that many people seem to overlook. Groovy doesn't compete with jython, pnuts, jruby, etc. They cooperate. No one directly profits from any of them, any one of them is welcome to reuse ideas and code from another, etc. It is like the flame wars of a year ago between OJB and Hibernate users (the developers didn't really get involved in any flaming) which never made sense. Both are great technologies, and both are welcome to see what the other is doing and use each others good ideas. Open source technologies support each other, they don't compete. It is not zero-sum.
By going the JSR route the Groovy team is deliberately relinquishing control over their language in order to make it easier for other people to use, and to make it more politically acceptable in famously large companies that would never consider a toy language. Groovy has aspirations far beyond being a little language -- and formalizing the process by which it is developed is a key step to achieving that. I am impressed in their faith that the JCP provides that framework -- it says a lot about changing perspectives on the JCP.
0 writebacks [/src/groovy] permanent link
Wed, 10 Mar 2004
I slapped together a Groovy rpm today. It's oriented towards Red Hat (places environment script in /etc/profile.d/
) but should work anywhere. This is nice to see:
[root@kasparov ~]# apt-get install groovy
Reading Package Lists... Done
Building Dependency Tree... Done
The following NEW packages will be installed:
groovy
0 packages upgraded, 1 newly installed, 0 removed and 18 not upgraded.
Need to get 4223kB of archives.
After unpacking 4787kB of additional disk space will be used.
Get:1 http://127.0.0.1 redhat/ES3/i386/java groovy 0:1.0b4-bmc [4223kB]
Fetched 4223kB in 0s (9425kB/s)
Executing RPM (-Uvh)...
Preparing... ########################################### [100%]
1:groovy ########################################### [100%]
[root@kasparov ~]#
I'm personally a tarball kinda guy, but some people like these rpm thingies ;-)
0 writebacks [/src/groovy] permanent link
Fri, 20 Feb 2004Glen complained that the example in my previous post was pretty bad, so here is a better one in honor of Andy ;-)
<step name="md5-passwords" type="groovy">
<script>
import groovy.sql.Sql
import java.security.MessageDigest
sql = new Sql(connection)
sql.queryEach("select password, user_id from users") {
MessageDigest md = MessageDigest.getInstance("MD5")
sql.execute("update users set password=? where user_id=?",
[md.digest(it.password.bytes), it.user_id])
}
</script>
</step>
=)
4 writebacks [/src/groovy] permanent link
Thu, 19 Feb 2004A big chunk of my day job is on a continuously evolving large application we host. Continuously evolving and hosting together mean lots of database migrations. We've put together a wonderfully handy tool to automate database migrations. It is really just a stateful dependency resolver with convenience things for working on a database. Up until now we've supported migration steps in SQL, BeanShell, and Java. After playing with GroovySql -- we do that now too.
<step name="switch-login-and-passcode" type="groovy">
<depends name="version-4.2"/>
<script>
import groovy.sql.Sql
sql = new Sql(connection)
sql.execute("create table foo as select * from user")
sql.execute("delete from foo")
sql.queryEach("select login, password from user") {
sql.execute("insert into foo (login, password) values (?, ?)",
[it.passcode, it.login])
}
sql.queryEach("select * from foo") {
println "Funny Looking Login: ${it.login}"
}
sql.execute("drop table foo")
</script>
</step>
I really like OJB (obviously), but O/R mapping is far from the answer all the time =) Groovy SQL rocks.
12 writebacks [/src/groovy] permanent link
Fri, 31 Oct 2003After my last real post (NFJS reactions) multiple people, including James Strachan and Bill de Hora, told me about Groovy. I had seen reference to it on James's blog and nosed around the wiki before, but it didn't lead anywhere. With all of the prompting I figured I needed to give it a good look over
I really like what I see. When I looked over the wiki previously I got an impression that they were cherry-picking from Python and Ruby and I didn't think the language was really being built around a strong set of design principles. I have learned the error of my ways, largely from chatting with James and Bob Mcwhirter in irc while trying to figure things out.
I started with a canonical "Hello, world" in the form:
This was based on code from the wiki. Running it proved a bit tricky (that is when I hit irc) until I was kindly told that it still requires boot-strapping from Java to get started but that wasn't too bad. A side effect of the boot-strapping process is that after I posted the boot-strap to the wiki in an original form of using a List to collect the command line args, Bob told me that Groovy doesn't care if it is a List or Array, it treats them the same. Good! However, "Hello world" errors out. James, being a brit, had long ago gone to bed and Bob is a self-described "the compiler guy" so I was left scratching my head and patching Groovy to behave like the wiki says it should (easily done, the code is beautifully factored and layed out).class Test { void main() { println("Hello World") } }
I play some more, pop up some Swing stuff, work out how it differs from Ruby closure style:
compared to["1", "2", "3"].each { foo | println(foo) }
etc. Digging around some more a *lot* of the ruby/perl/python convenience idioms have been placed on the GroovyObject. It is nice.["1", "2", "3"].each { |foo| puts foo }
Next morning I hop into irc again and sure enough James and Bob make time to help out. I mention the "hello world" problem and James tells me it is by design. The proper form is
Which makes my brain hurt for a moment. Using Java constructs is legal so you can still callclass Test { void main() { "Hello World".println() } }
System.out.println();
with impunity, but println()
has been made a function of the base object (GroovyObject) in the language. Groovy is very oo'ish in the sense that Smalltalk, Ruby, and Objective-C are very oo'ish. I like this as it maps nicely to how I think.
James describes the language as a dynamically typed, ruby-like language built on how the JVM works. That last part is an important incite into some of its bits. Ruby is built on C as a standalone tool. Groovy is specifically designed to enable Java developers to feel at home, and to interact well with Java. You can use groovy objects in Java, access their properties, methods, etc reflectively very easily. It playes nicely with Java and feels like message-passing oriented Ruby while still being a method-calling style language like Java. I like it, a lot.
Anyway, much discussion ensued and James wound up patching Groovy to accept println(...) as a global function. He had convinced me it shouldn't be done, but c'est la vie. I half think he did it to avoid having to change all the samples on the wiki (side not, he is a genious in what he wants to do with the wiki for documentation purposes, more on that in some other entry later).
Going back to the Java-centric/compatible design: Groovy used to manipulate and build on Java based tools seems to be very elegantly done. It uses extent Java technology as underpinnings for much of its functionaliy in ways that let you get to the lower level Java stuff through the abstractions. I haven't played with the JMX based remote objects implementation yet, for instance, but am excited about it (I don't know if that makes sense or not, I have only seen JMX as the control side of containers, have never had need/desire/itch to hack it -- now I might).
I need to write a web-based ldap administration tool in the near future so think I will use Groovy (and the Novell LDAP library) to give it a go and see if I can pare down typical Servlet folderol a bit. Will post as I learn.
1 writebacks [/src/groovy] permanent link
Tue, 28 Oct 2003
Those Wacky Maven and Groovy People...
Star Wars quote of the month from building Groovy via and old beta of Maven:
[mccallister@kite ~/src/groovy]$maven __ __ | \/ |__ Jakarta _ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0-beta-9-SNAPSHOT Attempting to download mx4j-SNAPSHOT.jar. INTERNAL ERROR Reference made to goal 'jar:jar' which has no definition.
Go Jar Jar!