JRuby 0.8.2 released Apache Beehive 1.0
Oct 02

LINQ 101 to Ruby 101 to Groovy 101

Groovy, Microsoft, Ruby, Tech Add comments

Jon Udell posted some code that he was playing with to test out LINQ.

The code takes his blog format, and filters based on the XML, and some internal datastructures.

Then Sam Ruby ported it to Ruby.

For some reason I just ported it to Groovy:

def d = ["2005-09" : "September 2005", "2005-08" : "August 2005"]
def a = ["greasemonkey", "ajax"]

def rss = new XmlParser().parse("blog.xml")

def xml = new groovy.xml.MarkupBuilder(new PrintWriter(System.out))

rss.channel.item.findAll { item ->
d.keySet().any { day ->
t(item.date) =~ day;
} && a.any { tag ->
t(item.tags) =~ tag;
}
}.sort { x, y -> t(y.date) <=> t(x.date) }.each { i ->
xml.item() {
month(d[d.keySet().find { key -> t(i.date) =~ key }])
date(t(i.date))
title(t(i.title))
tags(t(i.tags))
}
}

def t(node) { return node[0]!=null ? node[0].text() : '' }

There are some uglies in there (especially the “node to text” pain), but I do prefer the native build syntax that we have in Ruby and Groovy, compared to nesting new XElement("item", ....). They could easily add more sugar to make that work on the .NET side of course.

The other interesting differences are that I didn’t use XPath in the Groovy version, and the lack of SQL like stuff. Here it is just method chaining. No need for a special orderby, you simply do a sort. Of course, the beauty of LINQ is its polymorphism across XML, SQL, etc etc.

Update: New Version

John Wilson took out his namespace aware XmlSlurper (to access dc:date vs. date), and a new builder syntax that handle multiple objects:

def d = ["2005-09" : "September 2005", "2005-08" : "August 2005"]
def a = ["greasemonkey", "ajax"]

System.out << new StreamingMarkupBuilder().bind {
mkp.declareNamespace(dc: "http://purl.org/dc/elements/1.1/")

new XmlSlurper().parseText(blog).channel.item.findAll {item ->
d.any{entry -> item.date.text() =~ entry.key} &&
a.any{entry -> item.tags.text() =~ entry}
}.list().sort{x, y -> y.date.text() <=> x.date.text()}.each {i ->
item([{month d.find{entry -> i.date.text() =~ entry.key}.value}, i.date, i.title, i.tags])
}
}

2 Responses to “LINQ 101 to Ruby 101 to Groovy 101”

  1. John Wilson Says:

    I posted a slightly different Groovy version on the Groovy User list: http://permalink.gmane.org/gmane.comp.lang.groovy.user/5526

    It removes the node to text pain and takes a slightly different approach to looking up the date prefix in the Map

  2. sam Says:

    I think they have posted at http://www.linqhelp.com too!

Leave a Reply

Spam is a pain, I am sorry to have to do this to you, but can you answer the question below?

Q: What is the number before 3? (just put in the digit)