def CAR_RECORDS = '''
<records>
<car name='HSV Maloo' make='Holden' year='2006'>
<country>Australia</country>
<record type='speed'>Production Pickup Truck with speed of 271kph</record>
</car>
<car name='P50' make='Peel' year='1962'>
<country>Isle of Man</country>
<record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record>
</car>
<car name='Royale' make='Bugatti' year='1931'>
<country>France</country>
<record type='price'>Most Valuable Car at $15 million</record>
</car>
</records>'''
def records = new XmlSlurper().parseText(CAR_RECORDS)
def record = records.car[2].country
int index = 0
Boolean found = false
record.parent().parent().children().each {
if (it == record.parent()) {
found = true
} else if (!found) {
index++
}
}
assert index == 3
return index
Friday, December 11, 2009
Which Child Am I?
I don't know if this is worth blogging home about, but I've needed this solution a couple times, and I found myself referencing this blog entry draft, so I'll put it out there and maybe someone else will find it useful. The problem is I have an xml node, and I want to know the order it is (as an index integer) in relation to its siblings. You may have to modify this of course, if the children you are comparing are deeper down than 1.
Monday, December 7, 2009
Using Groovy from the .zip file
I had always had trouble launching groovysh or groovyConsole from the .zip releases of groovy, and always waited until they released the installer for Windows, never knowing why. There is a simple fix, but one that didn't occur to me right away. The cause is that the GROOVY_HOME variable needs set before startGroovy.bat tries to add it to the classpath, so just add
This also, of course, overrides whatever you have set as system or user variables, so you can safely play with other versions from the .zips without needing to change anything (or needing admin rights).
set GROOVY_HOME=..\to startGroovy.bat (anywhere before the classpath gets set), and let the good times roll...
This also, of course, overrides whatever you have set as system or user variables, so you can safely play with other versions from the .zips without needing to change anything (or needing admin rights).
Thursday, December 3, 2009
My Second Wave Bot
Inspired by Piratify, I decided to make a bot that makes everyone talk like Yoda (Yodaspeak as I call it). The bot lives at yodaspeakify.appspot.com, and can be added by adding yodaspeak@appspot.com to your wave. The sourcecode is available here. It works, but needs more work to improve its results.
Monday, November 23, 2009
My First Wave Bot
I finally got my Wave invite, and I immediately got interested in coding with it. I recently finished creating a bot for it that allows you to search WorldCat from inside Wave. The main servlet is in Groovy, the profile is in Java. Their tutorial pretty much works, though one of the methods was renamed:
getRobotProfileUrl() should be called getRobotProfilePageUrl() (there's a request filed to fix this). Google's plugin for Eclipse also works very well. JetBrains also has a plugin for IDEA, though I didn't test this. In their sample project SpringSource has a build script that uses AntBuilder, which I modified to use the folder structure that was already created by the Eclipse plugin. I successfully built with this and deployed the app using appcfg.cmd from the SDK. I used straight html for the bot's profile page, but in their sample SpringSource shows how you could use the MarkupBuilder in groovlets.
Anyway, the app is deployed on the Google App Engine here, it's homepage (where the sourcecode is also available) is here. You can add it to your waves by adding worldcat-bot@appspot.com. For even more bots, check out the list. Mine's listed too. There is another list out there, but it doesn't seem used as much.
Some gotchas:
Anyone in the conversation (called a Wave) can edit any of the messages (blips). Side conversations can occur in the same stream, these side conversations are called wavelets. APIs exist to have bots in a conversation that automate tasks (such as links for searches, posting the conversation to a blog, bringing in text from a feed, or converting everyone's text to pirate talk) and for gadgets that let you put different kinds content inside the conversation, such as documents, polls, etc. Google plans to open source most of Wave once it's finished, allowing other 'federated' servers to become Wave providers, and they plan to make the protocol they use the predominant protocol on the internet. The Google Wave Federation Protocol is itself built off XMPP (the same protocol Jabber and GoogleTalk use). They have bindings for Python and Java currently (I've heard the Python API is not as polished as the Java one, but I don't know that for sure and I'm sure it will improve), and will probably be adding more languages in the future to support their goal of making their protocol #1. Wikipedia has a pretty good article on Wave as well.
I still have Wave invites left for my friends, if you're interested.
getRobotProfileUrl() should be called getRobotProfilePageUrl() (there's a request filed to fix this). Google's plugin for Eclipse also works very well. JetBrains also has a plugin for IDEA, though I didn't test this. In their sample project SpringSource has a build script that uses AntBuilder, which I modified to use the folder structure that was already created by the Eclipse plugin. I successfully built with this and deployed the app using appcfg.cmd from the SDK. I used straight html for the bot's profile page, but in their sample SpringSource shows how you could use the MarkupBuilder in groovlets.
Anyway, the app is deployed on the Google App Engine here, it's homepage (where the sourcecode is also available) is here. You can add it to your waves by adding worldcat-bot@appspot.com. For even more bots, check out the list. Mine's listed too. There is another list out there, but it doesn't seem used as much.
Some gotchas:
- You cannot test robots without deploying them to the Google App Engine, this makes you waste some of the number of deployments you have on the free account (currently you get 1000).
- Wave caches its bots, so you have to change the version in appengine-web.xml (I don't think you have to change the version in capabilities.xml too unless the capabilities have also changed, but I've been changing both to match). They tell you this, but you have to be careful because even though you may have deleted the old version if you reuse a version descriptor text Wave may still try to call the old version and you will get a ServletUnavailable exception and waste another deployment. You have to wait for the re-caching to occur.
- If you are using Groovy, you have to upload the groovy-all jar in the war/WEB-INF/lib directory (the war folder can be a different name, but that is the convention used by the Eclipse plugin).
Anyone in the conversation (called a Wave) can edit any of the messages (blips). Side conversations can occur in the same stream, these side conversations are called wavelets. APIs exist to have bots in a conversation that automate tasks (such as links for searches, posting the conversation to a blog, bringing in text from a feed, or converting everyone's text to pirate talk) and for gadgets that let you put different kinds content inside the conversation, such as documents, polls, etc. Google plans to open source most of Wave once it's finished, allowing other 'federated' servers to become Wave providers, and they plan to make the protocol they use the predominant protocol on the internet. The Google Wave Federation Protocol is itself built off XMPP (the same protocol Jabber and GoogleTalk use). They have bindings for Python and Java currently (I've heard the Python API is not as polished as the Java one, but I don't know that for sure and I'm sure it will improve), and will probably be adding more languages in the future to support their goal of making their protocol #1. Wikipedia has a pretty good article on Wave as well.
I still have Wave invites left for my friends, if you're interested.
Wednesday, November 11, 2009
Functional Programming
I know this is old news, but it's new to me. I've been thinking about an article by Paul Graham which is basically about how functional languages are superior to OOP and other imperative languages, and languages are shifting towards functional programming in general, and LISP in particular. I disagree on both counts. Ignoring the fact that whether its right or not, OOP isn't going away any time soon, I think that there are certainly problems that are better suited to that paradigm, but there are many problems that are not. This is a good part of the reason that we see more multi-paradigm languages that pure languages.
I specifically object to the example he chose to demonstrate the 'power' of Lisp. He chooses a problem that Lisp and similar languages are naturally going to win. He wants to return a method that is an incrementer as the result. Its going to be ugly in any language where methods are not first class objects.
He also claims that design patterns exist to make up for shortcomings in a language. There is a related question on StackOverflow. The study referenced there states that 7 of the 23 patterns in the GoF still applied in functional languages. Even Lisp is not a purely functional language and needs what can be regarded as a design pattern (Monad) to allow for something stateful (like IO). (When was the last time you wrote a program that didn't use some kind of IO?).
Languages are not becoming more and more like Lisp, though many of them did borrow some concepts from Lisp. One of the main reasons for this is that Lisp was one of the first high level languages (even before C). Yes, things like garbage collection, dynamic typing, and recursion were initially eschewed by the programming community only to be later made mainstream. This is for reasons of computing power rather than a sudden realization that Lisp had it right all along. Paul Prescod talks about how Python isn't moving towards Lisp and how many former Lispers have adopted Python. I think Paul's statements stem from having sour grapes over the lack of success of his pet language more than historical fact.
That being said, Java certainly isn't perfect and has been constrained by Sun's unwillingness to break compatibility to add new features. Wouldn't it be better to say languages like Java could benefit from some additional Lisp-like options, such as lamda (available as closures in groovy) and first class methods (available in Scala) rather than immature statements like Lisp >> Java? While I agree that there might be a place for a language that keeps things simple to help curb mistakes, I would rather see greater flexibility and choice given to empower the programmer, allowing for whatever style best suites the problem at hand. Some problems lend themselves to functional programming, and some problems are stateful in their very nature. I find OOP easier to think in, because we fairly naturally think of things as interactions of systems. Though, this is perhaps overused currently in our industry for problems it shouldn't be used to tackle.
For this reason, I would like to study and work with functional languages more than I currently am to recognize and take advantage of those situations in which functional languages are the right choice (assuming the decision is up to me).
On a related note, the Computer Language Benchmarks Game is also good fun, for those who find religious wars amusing. 99 bottles of beer is also an interesting reference. It is programs that print the lyrics to the song 99 bottles of beer, in many languages. (check out an Erlang version, Lisp version, and a Java version).
Related links
http://norvig.com/design-patterns/
http://www.norvig.com/lisp_talk_final.htm
http://www.norvig.com/python-lisp.html
http://www.paulgraham.com/power.html
Something unrelated, but funny
http://www.willamette.edu/~fruehr/haskell/evolution.html
I specifically object to the example he chose to demonstrate the 'power' of Lisp. He chooses a problem that Lisp and similar languages are naturally going to win. He wants to return a method that is an incrementer as the result. Its going to be ugly in any language where methods are not first class objects.
He also claims that design patterns exist to make up for shortcomings in a language. There is a related question on StackOverflow. The study referenced there states that 7 of the 23 patterns in the GoF still applied in functional languages. Even Lisp is not a purely functional language and needs what can be regarded as a design pattern (Monad) to allow for something stateful (like IO). (When was the last time you wrote a program that didn't use some kind of IO?).
Languages are not becoming more and more like Lisp, though many of them did borrow some concepts from Lisp. One of the main reasons for this is that Lisp was one of the first high level languages (even before C). Yes, things like garbage collection, dynamic typing, and recursion were initially eschewed by the programming community only to be later made mainstream. This is for reasons of computing power rather than a sudden realization that Lisp had it right all along. Paul Prescod talks about how Python isn't moving towards Lisp and how many former Lispers have adopted Python. I think Paul's statements stem from having sour grapes over the lack of success of his pet language more than historical fact.
That being said, Java certainly isn't perfect and has been constrained by Sun's unwillingness to break compatibility to add new features. Wouldn't it be better to say languages like Java could benefit from some additional Lisp-like options, such as lamda (available as closures in groovy) and first class methods (available in Scala) rather than immature statements like Lisp >> Java? While I agree that there might be a place for a language that keeps things simple to help curb mistakes, I would rather see greater flexibility and choice given to empower the programmer, allowing for whatever style best suites the problem at hand. Some problems lend themselves to functional programming, and some problems are stateful in their very nature. I find OOP easier to think in, because we fairly naturally think of things as interactions of systems. Though, this is perhaps overused currently in our industry for problems it shouldn't be used to tackle.
For this reason, I would like to study and work with functional languages more than I currently am to recognize and take advantage of those situations in which functional languages are the right choice (assuming the decision is up to me).
On a related note, the Computer Language Benchmarks Game is also good fun, for those who find religious wars amusing. 99 bottles of beer is also an interesting reference. It is programs that print the lyrics to the song 99 bottles of beer, in many languages. (check out an Erlang version, Lisp version, and a Java version).
Related links
http://norvig.com/design-patterns/
http://www.norvig.com/lisp_talk_final.htm
http://www.norvig.com/python-lisp.html
http://www.paulgraham.com/power.html
Something unrelated, but funny
http://www.willamette.edu/~fruehr/haskell/evolution.html
Groovy - Sometimes you still need a semicolon
I Was ploughing through my overly-large blogroll the other night when this article caught my eye.
http://groovy.dzone.com/articles/groovy-sometimes-you-still
I gave it a read, because I wanted to know all the cases where you had to have a semicolon.
He gives two examples, the first of which he’s wrong about, it works fine in 1.6.5 and I believe it works for anything >= 1.6.
This second one (not the exact same example he used) does need a semicolon
Should be
This is only the case if you have two closure calls next to each other with nothing in between.
Are there other times when you need a semicolon at the end of the line (assuming only one statement per line)?
http://groovy.dzone.com/articles/groovy-sometimes-you-still
I gave it a read, because I wanted to know all the cases where you had to have a semicolon.
He gives two examples, the first of which he’s wrong about, it works fine in 1.6.5 and I believe it works for anything >= 1.6.
def list = [1,2,3] as List<Integer>
println listThis second one (not the exact same example he used) does need a semicolon
{-> assert true == true }()
{-> assert false == false }()Should be
{-> assert true == true }();
{-> assert false == false }()This is only the case if you have two closure calls next to each other with nothing in between.
{-> assert true == true }()
println ""
{-> assert false == false }()works fine.Are there other times when you need a semicolon at the end of the line (assuming only one statement per line)?
Friday, November 6, 2009
Groovy 1.7 Beta 2 Available
It’s a bit of old news, but I don’t remember seeing anything about it until today.
It was available 12 Oct, and Windows installer binaries were available 18 Oct. Get yourshere.
A draft of the current features is available at http://docs.codehaus.org/display/GROOVY/(draft)+Groovy+1.7+release. This release is mostly bug fixes, with two notable improvements. They have added the ability to alter the meaning of Groovy Truth. This lets you add some truth to your own class by adding the asBoolean method:
And of course, using ExpandoMetaClass, you can alter the behavior for Groovy classes that already have a Groovy Truth defined:
They’ve also added stylish outputs for assertion failures (I guess taken from the Spock testing framework):
It was available 12 Oct, and Windows installer binaries were available 18 Oct. Get yourshere.
A draft of the current features is available at http://docs.codehaus.org/display/GROOVY/(draft)+Groovy+1.7+release. This release is mostly bug fixes, with two notable improvements. They have added the ability to alter the meaning of Groovy Truth. This lets you add some truth to your own class by adding the asBoolean method:
class Foo {
String value
boolean asBoolean() { value == "something true" }
}
assert new Foo(value: "something true")
assert !new Foo(value: "teh cake is a lie")
And of course, using ExpandoMetaClass, you can alter the behavior for Groovy classes that already have a Groovy Truth defined:
Integer.metaClass.asBoolean { int value ->
return value > 0
}
Integer foo = 7
assert foo.asBoolean()
They’ve also added stylish outputs for assertion failures (I guess taken from the Spock testing framework):
int foo = 0
int bar = 1
assert foo == bar
will display:Assertion failed:
assert foo == bar
| | |
0 | 1
false
Subscribe to:
Posts (Atom)