When Type Systems Attack

Groovy’s type system can sometimes have funny interplay and unexpected results. For example, these assertions are true:

However, mixing in a Map into this causes some complications:

This might not seem like a big issue, but it can cause some real headaches. When failing an assertion the message printed only prints values, not types. Because of this you may occasionally run into less than helpful error messages like:

And this can be awfully confusing. One prime example of this is with GORM domains. GORM defaults primary keys to be Longs so if you use a primary key as a map key you could run into some pretty confusing error cases that your tests don’t explain as helpfully as you’d like.

Grails Custom Validation messages

Grails' GORM provides convenient ways to define many different constraints for inputing properties including basic ones like max, equal, & notEqual to more specific ones like creditCard, url, & email (full list here under Quick Reference). But sooner or later you’ll want to create your own custom validator. This can be done by providing a validator closure to your domain, for example:

Now, in this example a domain will validate all of the fields, including the user’s favorite prime (to a degree of certainty). However, if the prime number certainly isn’t prime then the error message provided when validation fails (through validate or save) will be:

favoritePrime does not pass custom validation.

That probably isn’t a helpful message to eventually pass back to the user, they might guess what the mysterious “custom validation” is in this case, but certainly not in all others.

So what is the solution? You might try passing an error message back, but that won’t work; you’ll get the same message again. It turns out the proper approach is to return a key from your message.properties file. If the key exists in the proper localization file (e.g. French is messages_fr.properties) then it will use that string. A simple modification to the validator above will solve this:

Adding the line:

my.localized.not.prime.message=The number {2} is not prime.

Will cause Grails to generate a much more useful validation failed message. As you can probably guess the {2} will be replaced with the value inputed by the user.

You can include additional values to your message by returning an array. The first element should be a message key (e.g. ‘my.localized.not.prime.message’) and the subsequent entries will be interpolated into the message starting at index 3. So, if you returned ['my.localized.not.prime.message', 5] you could have the message: my.localized.not.prime.message=The number {2} is not prime, {3} is an example of a prime. And in this case if the user passed in 4 they would end up with the message:

The number 4 is not prime, 5 is an example of a prime.

Of course, if you aren’t using a prime number validator multiple times in your code it may seem silly to have a special key/value pair dedicated to primes. Another option is to use a key/value pair dedicated to that field. You can do this simply by using the code in the first example and addding a field to your message.properties file like:

Groovyist.favoritePrime.validator.invalid=The number {2} is not prime.

Much of this is documented in the validator docs.

Perl to Groovy Mappings (An Introduction)

Recently I took a job with a startup that is using Groovy as their main language. I find the language to be similar to several other languages and they have some comparisons on their site, however one comparison they are missing is to Perl. Since I'm learning Groovy anyway and the two are sufficiently similar that I thought I'd give it a shot.

Before I start with the articles there are a few important things to note about Groovy:

  1. Groovy autoboxes, as such it is completely legitimate to write `"I like cheese".someMethodOnStrings()`.
  2. Groovy automatically makes a variable named `it` as the only parameter for lambda function if no parameter list is given, meaning that: `def foo = { it * 2}` is similar to `def foo = { it -> it * 2}`.
  3. Groovy's syntax provides an alternate way to list parameters for a method call when the last parameter is a lambda function meaning that `someData.someMethod(1,2, { it + 2})` is the same as `someData.someMethod(1,2) { it + 2}`, this is useful for methods that loop over lists, like `each`.

 

Perl to Groovy Mapping (Iterating)

This entry will primarily go over various approaches towards iterating over structures of data. This will include basic looping as well as equivalents to Perl’s map & grep.

This is not intended to be an exhaustive guide or a best practice for either language. The attempt, as with all articles in this series, is to provide a basic set of mappings between the languages.

Iterating over collections

To loop over all the items in an array in Perl you would probably use the for loop construct:

for my $item (@array) {…}

You could do something similar in Groovy using the each method on collections:

list.each {}

To loop over all the keys in a hash (or Map) you can combine the above with the keys builtin:

for my $key (keys(%hash)) {…}

In Groovy you simply use a lambda that accepts two parameters.

myMap.each { key, _value ->  }

Looping over all the values is similar to the examples above in both, so I will skip that. Looping over each entry in the hash with both the key and value in Groovy is the same as the example above, in Perl you would have to use each, which I don’t like.

It is important to note that with Groovy’s each different things are passed in based on the number of parameters. The example above gave each a 2 parameter lambda and so the lambda got inputs of [key, value]. Had a 1 parameter lambda been passed in then that lambda would have received an Entry object that had accessors for the key and value.

Iterating over a Set of Integers

Both Perl and Groovy provide many ways to iterate over a range. One popular approach in Perl is to use the dot-dot range operator (..) and for looping construct. By using this it is simple to print all the numbers between one and ten:

for my $num (1..10) { print $num }

Groovy has a similar approach:

(1..10).each { print it }

Groovy has a couple other ways to do the same thing, for example numbers have an upto method attached to them that can be used to iterate. As such, the same thing above could be written as:

1.upto(10) { print it }

Of course, Perl also has the ability to loop via the while looping construct and Groovy could loop using a for in on top of what I’ve listed here.

If you wanted to iterate over a set of integers that didn’t increment by one in Perl you might use map and for like this:

for my $multiple_of_five ( map { $_ * 5 } 1..5) {…}

Or you might use grep and for like this:

for my $multiple_of_five ( grep { not $_ % 5 } 1..25) {…}

Or, of course, you could pick up a useful module, like Math::Sequence.

In Groovy you would simply do this:

5.step(25,5) {}

Mapping a List

Perl helpfully provides the map builtin to easily map a list of values from one to another. For example, were a developer wanting to square all the values in a list they would:

my @squared = map { $_**2 } @original_values

The same thing can be performed in Groovy using the collect() method on collections:

List squared = originalValues.collect { it.power(2) }

Grepping a List

Perl provides the grep builtin to easily filter values out of a list and provide a new list with only the remaining values. For example, if a developer was looking for all the items in a list that were odd they could:

my @odd = grep { $_ % 2 } @numbers

To do this in Groovy they would use the findAll method that exists on collections:

List odd = numbers.findAll { it % 2 }

Grepping for the First Item in a List

Perl has a number of modules which are considered ‘core’. It is reasonable to assume any core module is installed and readily available. To get the first item in a list that matches some criteria a Perl developer could use the example above for grepping a list and shift off the top, but more likely they would use List::Util’s first like this:

my $first_odd = first { $_ % 2} @numbers

A similar approach in Groovy could be done via the find method on collections:

def firstOdd = numbers.find { it % 2 }