Saturday, June 4, 2011

Ten Groovy One Liners to Impress Your Friends

I started working on this blog post and the associated code examples after reading the plethora of blog posts this week discussing "ten" one liners in various programming languages. It all seems to have started with Marcus Kazmierczak's 10 Scala One Liners to Impress Your Friends, which then led to (not in this order) 10 Ruby One Liners to Impress Your Friends, 10 Python one liners to impress your friends, 10 Clojure One Liners to Impress Your Friends, F# One liners to impress your friends, 10 Haskell One Liners to Impress Your Friends, 10 CoffeeScript One Liners to Impress Your Friends, and 10 C# One Liners to Impress Your Friends.

I felt that it was an unforgivable omission to not have Groovy included in the plethora of covered languages in these posts and embarked on writing my own examples. It was only after I finished the first eight that I realized that Arturo Herrero had already addressed this glaring omission in the post 10 Groovy One Liners to Impress Your Friends. Because I had already done most of the work on my own post, I have decided to include my example and this post anyway. It is interesting to see how many things I did the same way, but there are some minor differences in some of the one-liners. I did not re-invent #9, #10, and the bonus #11 after I realized the existence of this other post. I have included the same approaches for those last three in my example here for completeness. Note that there is also a different take on the Scala example as well. If Scala gets two perspectives, shouldn't Groovy get two as well?

1. Multiply Each List Item by Two

Groovy's GDK's Collection.collect(Closure) makes this a breeze.

(1..10).collect{it * 2}

2. Summing List of Numbers

Just when you thought it couldn't get any easier...

The GDK's Collection.sum() method does just that.

(1..1000).sum()

3. Verifying Existence of List Item in String

This is an opportunity to show off Groovy's Collection.inject(Object, Closure).

def wordList = ["Groovy", "dynamic", "Grails", "Gradle", "scripting"]
def string = "This is an example blog talking about Groovy and Gradle."
wordList.inject(false){ acc, value -> acc || string.contains(value)}

4. Reading A File

Groovy's GDK's File makes reading a file's contents as a String or as a List of Strings easier than falling off a log.

new File("data.txt").text
new File("data.txt").readLines()

5. Happy Birthday to You

This one-liner prints the first verse (and only verse for most of us!) "Happy Birthday" song based on a provided parameter named 'name.'

(1..4).collect{"Happy Birthday " + ((it == 3) ? "dear ${name}" : 'to You')}.each{line -> println line}

6. Filter List of Numbers

Scala and Groovy implementations of this one liner are also covered in James Strachan's post "a groovy scala example" and the Groovy version is inspired by Guillaume Laforge's referenced Tweet (proof that one can put something of substance within 140 characters).

def (passed, failed) = [49, 58, 76, 82, 88, 90].split{it > 60}

7. Fetch/Parse an XML Web Service

def content = new XmlSlurper().parse("http://search.twitter.com/search.atom?&q=groovy")

8. Finding Minimum/Maximum in a List

It doesn't get any easier than this thanks to the apropos Groovy GDK Collection methods min() and max().

[14, 35, -7, 46, 98].min()
[14, 35, -7, 46, 98].max()

9. Parallel Processing

One of the great new features of Groovy 1.8 is the bundling of GPars 0.11 in the Groovy distribution. GPars is described as a project that "offers developers new intuitive and safe ways to handle Java or Groovy tasks concurrently, asynchronously, and distributed by utilizing the power of the Java platform and the flexibility of the Groovy language."

It was as a I was about to write an example of Groovy parallel processing using GPars that I discovered the existence of Arturo Herrero's blog post. I use a slightly adapted version of his example here. It assumes the existence of an initialized dataList and the existence of a method called processItem.

groovyx.gpars.GParsPool.withPool{def result = dataList.collectParallel{processItem(it)}}

10. Sieve of Eratosthenes

I borrowed this example from Arturo Herrero's blog post, which in turn adapted it from a comment on RJ Salicco's Groovy Prime Numbers post.

def t = 2..100
(2..Math.sqrt(t.last())).each { n -> t -= ((2*n)..(t.last())).step(n) }
println t

Bonus: FizzBuzz

The original Scala One Liners post did not have this "bonus" item, but it got introduced (CoffeeScript examples) as the dam broke and the plethora of programming language one liners posts came gushing forth. This example is based on a 2007 blog post called Using FizzBuzz to Find Developers who Grok Coding. In that Imran on Tech post, the author states an example of a FizzBuzz coding puzzle he gives to software developers in interviews:
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print "FizzBuzz".

This example is unchanged from that provided in Arturo Herrero's blog post. This is arguably the "most Groovy" of all the examples here because nearly every piece of this example is Groovy goodness. It begins with Groovy-specific (meaning not available in Java) syntax for iterating from 1 through 100, uses the Groovy each to process a closure which uses the built-in println and uses Groovy's GString and placeholder syntax for good effect. In the midst of all this, a couple of ternary operators (available in Java) are thrown in for good measure and finally an Elvis operator wraps it all up.

(1..100).each{println "${it%3?'':'Fizz'}${it%5?'':'Buzz'}" ?: it }

It is arguable that the Groovy version is even more readable than the CoffeeScript versions, though that opinion is undoubtedly affected by my greater familiarity with Groovy syntax.


The Value of the One Liner Exercise

Dion Almaer has stated in an appropriately geeky way that "the 'best' programming language, doesn’t mean the one that creates the lowest wc -l." However, in the same post, he also points out that "languages such as Ruby [and] Groovy ... allow me to get closer to the zen of 'expressing everything I want, and need to get across... but not more'. Every operator/method tells me a lot."

I believe that the examples in this post and in the other "One Liners" posts provide examples and the good and the bad of one liners. Some of the examples here (such as getting the minimum and maximum from a collection, getting a file's contents, and summing a collection's elements) are concise and highly readable at the same time. Most large scale software project cannot afford the unmaintainable and unreadable code that can come from cramming a bunch of functionality into a single line via archaic representations. However, a language with a carefully crafted syntax can, as some of these examples show, allow for concise and highly readable expression. It's really advantageous when one can get readability and conciseness.

I found personal benefit from writing these examples and writing this post. For one, I was happy to realize that I'm definitely far more comfortable with Groovy and Groovy-isms than I was when I first started using Groovy. A second benefit of this exercise was exposure to new Groovy concepts. Before writing these examples, I had never used the Collection.collect(Closure) or Collection.inject(Object, Closure) methods. In trying to figure out how to implement these one liners, I also was reminded how nice the GDK API documentation is because I was able to figure out Groovy equivalents using that documentation. It was a nice challenge to work out some Groovy solutions in as concise a manner as possible and that challenge made this exercise even more useful.

A final advantage of true Groovy one liners is the ability to employ such one liners with the Groovy launcher's -e option. I have blogged about this groovy -e feature in previous posts including jrunscript and Groovy.


Can These Examples Be Even Groovier?

Although Arturo Herrero's blog post and my blog post provide Groovy implementations of these 10+1 one liners, it is likely that Groovy developers out there can make some of these examples even Groovier. If you can, please pass along those improvements via comment on this blog, via your own blog, or via Tweet. Many of the one liners posts for the other languages had community feedback on ways to improve or at least provide an alternative to the original authors' ideas.


Other Groovy One Liners

I'm not going to do it here because this post is already sufficiently lengthy, but I think an interesting idea for a future post (or for someone else to post) is another "set" of one liner implementations written in Groovy. For example, I'm a big fan of this one liner in Groovy for printing out the available TimeZones for a particular JVM implementation.

TimeZone.getAvailableIDs().sort().each{println it}

An example of running this using the Groovy native launcher and its -e option is shown next.



Conclusion

Thanks to Marcus Kazmierczak for starting off this multi-language coverage of one liners. It has made for interesting reads of others' posts and how those languages are similar and different in resolving the same issues. It has also led to a very insightful activity in implementing Groovy equivalents of these one liners. This exercise has been a reminder of the concise expressiveness of the Groovy language (the "in" crowd calls it "fluency"). Groovy is certainly a fluent language.

7 comments:

@DustinMarx said...

Arturo,

When I was about to start work on a Groovy implementation of the Sieve of Eratosthenes, I was glad to see that you already had one out there. Thanks for the post and for taking the time to provide feedback here.

Dustin

bootz15 said...

Not sure what #3 is supposed to help with. I find this example of inject much more helpful:


def wordList = ["Groovy", "dynamic", "Grails", "Gradle", "scripting"]
def string = "This is an example blog talking about Groovy and Gradle."
println wordList.inject([]){ acc, value -> acc << string.contains(value)}

Ted Naleid said...

I'd use a regex for #3 so there is only one pass (and it returns the matched item to boot:

println string.find(wordList.join("|"))

replace with findAll to see all matches

thevery said...

why not use any for #3?
wordList.any {string.contains(it)}

@DustinMarx said...

bootz15, Ted, and thevery:

Thanks for the alternate approaches for the third one liner.

Dustin

bootz15 said...

(Sorry, just couldn't resist.) To sum it up:

//Any found?
println wordList.inject(false) { acc, value -> acc || string.contains(value) }
println wordList.any {string.contains(it)}

//All found?
println wordList.inject(true) { acc, value -> acc && string.contains(value) }
println wordList.every {string.contains(it)}

//Return found
println wordList.inject([]) { acc, value -> string.contains(value) ? acc << value : acc; }
println string.findAll(wordList.join("|"))
println wordList.findAll{string.contains(it)}

I didn't know about the .join("|") method -- wow! It bears mentioning that .inject() can be useful in a functional style of programming.

@DustinMarx said...

bootz15,

I'm glad you couldn't resist because your collection is great! Thanks for sharing.

Dustin