Elvis carried away by spaceships

I love teaching Groovy to existing Java developers, because they have such a hard time holding back Tears Of Joy when they see how much easier life can be. Today, though, I did a quick demo that resulted in a line of Groovy that was so amusing I had to post it here.

Consider a trivial POGO (Plain Old Groovy Object) called Course:
[sourcecode langauge=”groovy”]
class Course
String name
int days
String toString() { "($name,$days)" }
The goal was to take a collection of courses and sort it by the number of days. That’s really easy in Groovy:
[sourcecode language=”groovy”]
def courses = [
new Course(name:’Groovy’,days:4),
new Course(name:’Grails’,days:3),
new Course(name:’Spring’,days:4),
new Course(name:’Hibernate’,days:3)

assert courses.toString() == ‘[(Groovy,4), (Grails,3), (Spring,4), (Hibernate,3)]’

courses.sort { it.days }

assert courses*.days == [3, 3, 4, 4]
The sort method in the java.util.Collection class is part of the Groovy JDK, meaning it’s one of the methods Groovy adds to the standard Java libraries. It takes a closure of either one or two arguments. In this case, I’m using the one-argument closure, which is used to select a property on which to base the sort. By specifying it.days in the closure, I’m telling the sort method to sort the courses based on their days property. Then I verify that the sort worked by checking that the courses are the right order, using the spread-dot operator to just look at the number of days.

In class the question that always comes up is, can I sort by days and then by name? In other words, if two courses have the same number of days, can I then sort by the name property?

That’s what the two-argument closure on the sort method is for. The two arguments are references to any pair of courses, and the closure should return a negative number, zero, or positive number according to whether the first course is less than, equal to, or greater than the second.

Here’s where things get amusing. The sort I want is:
[sourcecode language=”groovy”]
courses.sort { a,b ->
a.days <=> b.days ?: a.name <=> b.name

assert courses.toString() == ‘[(Grails,3), (Hibernate,3), (Groovy,4), (Spring,4)]’
The body of the closure on sort uses the spaceship operator <=>, which returns -1, 0, or 1 depending on whether the left side is less than, equal to, or greater than the right side. I use spaceship to compare the days properties. Then I add the Elvis operator ?: which means if the days comparison is not zero, use it, but otherwise use the following comparison, which uses another spaceship to compare by name.

It’s only after writing the code in class that one of the students pointed out that I had Elvis in between two spaceships, leading to the following observations:

  1. The spaceships are there to return Elvis to his home planet
  2. It takes two spaceships, working in tandem, to carry Elvis away, in much the same way two swallows can carry a coconut in tandem
  3. Therefore, the Elvis being carried away must be the fat Elvis from the 70s, rather than the thin, cool Elvis from the 50s

Either way, after the sort is finished, Elvis has left the building.

Thank you, thank you very much.

2 responses to “Elvis carried away by spaceships”

  1. […] Elvis carried away by spaceships (Ken Kousen, reporting for Kousen IT) Share and Enjoy: […]

  2. […] found this post. You can try using this in your […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.