views:

1735

answers:

14

It seems like Groovy was forgotten in this thread so I'll just ask the same question for Groovy.

  • Try to limit answers to Groovy core
  • One feature per answer
  • Give an example and short description of the feature, not just a link to documentation
  • Label the feature using bold title as the first line

See also:

  1. Hidden features of Python
  2. Hidden features of Ruby
  3. Hidden features of Perl
  4. Hidden features of Java
+9  A: 

Using hashes as pseudo-objects.

def x = [foo:1, bar:{-> println "Hello, world!"}]
x.foo
x.bar()

Combined with duck typing, you can go a long way with this approach. Don't even need to whip out the "as" operator.

Robert Fischer
new to Groovy - that's very nice indeed.
Steve B.
+17  A: 

Using the spread-dot operator

def animals = ['ant', 'buffalo', 'canary', 'dog']
assert animals.size() == 4
assert animals*.size() == [3, 7, 6, 3]
What does the third line mean?
ripper234
From context it means invoke the size method on each array element and return an array of the results. Pretty cool actually :-)
Michael Rutherfurd
Ah. Now that I see it, it is rather cool :)
ripper234
A: 

Argument reordering with implicit arguments is another nice one.

This code:

def foo(Map m=[:], String msg, int val, Closure c={}) {
  [...]
}

Creates all these different methods:

foo("msg", 2, x:1, y:2)
foo(x:1, y:2, "blah", 2)
foo("blah", x:1, 2, y:2) { [...] }
foo("blah", 2) { [...] }

And more. It's impossible to screw up by putting named and ordinal arguments in the wrong order/position.

Of course, in the definition of "foo", you can leave off "String" and "int" from "String msg" and "int val" -- I left them in just for clarity.

Robert Fischer
I wish this were the case, but currently Groovy (1.6) only supports named arguments for object constructors. You can use this syntax for method calls, but it packages any named arguments up into a Map, then looks for foo(Map).
Cody Casterline
I'm confused as to what you think I said that implied different.
Robert Fischer
+12  A: 

Anyone know about Elvis?

def default = "hello";
def obj = null;

def obj2 = obj ?: default;   // sets obj2 to default
obj = "world"

def obj3 = obj ?: default;  // sets obj3 to obj (since it's non-null)

Thank you very much.

Bill James
is this the same as the null coalescing operator (??) from C#?
Alex Baranosky
It would seem so, yes, though I had to look up the C# op.
Bill James
+7  A: 

For testing java code with groovy, object graph builder is amazing:

def company = builder.company( name: 'ACME' ) {
   address( id: 'a1', line1: '123 Groovy Rd', zip: 12345, state: 'JV' )
   employee(  name: 'Duke', employeeId: 1 ){
      address( refId: 'a1' )
   }
}

Standard feature, but still really nice.

http://groovy.codehaus.org/ObjectGraphBuilder

krosenvold
+4  A: 

Unlike Java, in Groovy, anything can be used in a switch statement, not just primitive types. In a typical eventPerformed method

switch(event.source) {
   case object1:
        // do something
        break
   case object2:
        // do something
        break
}
Rui Vieira
+16  A: 

The with method allows to turn this:

 myObj1.setValue(10)
 setTitle(myObj1.getName())
 myObj1.setMode(Obj1.MODE_NORMAL)

into this

 myObj1.with {
    value = 10
    title = name
    mode = MODE_NORMAL
 }
Rui Vieira
that brings me old memories about object pascal :-)
fortran
+5  A: 
println 
"""
Groovy has multi-line strings.
Hooray!
"""
John Flinchbaugh
Ah, the beauty of multi-line strings. Every language should adopt these.
ripper234
+1  A: 

Closures can make all the old try-finally games of resource management go away. The file stream is automatically closed at the end of the block:

new File("/etc/profile").withReader { r ->
    System.out << r
}
John Flinchbaugh
+4  A: 

In groovy 1.6, regular expressions work with all of the closure iterators (like each, collect, inject, etc) and allow you to easily work with the capture groups:

def filePaths = """
/tmp/file.txt
/usr/bin/dummy.txt
"""

assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file -> 
        "$file -> $path"
    } ==  ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
Ted Naleid
+10  A: 

Finding out what methods are on an object is as easy as asking the metaClass:

"foo".metaClass.methods.name.sort().unique()

prints:

["charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo",
 "compareToIgnoreCase", "concat", "contains", "contentEquals", "copyValueOf", 
 "endsWith", "equals", "equalsIgnoreCase", "format", "getBytes", "getChars", 
 "getClass", "hashCode", "indexOf", "intern", "lastIndexOf", "length", "matches", 
 "notify", "notifyAll", "offsetByCodePoints", "regionMatches", "replace", 
 "replaceAll", "replaceFirst", "split", "startsWith", "subSequence", "substring", 
 "toCharArray", "toLowerCase", "toString", "toUpperCase", "trim", "valueOf", "wait"]
Ted Naleid
+1 just saved mi a tons of time :)
Dan
+2  A: 

Closure-Based Interface Implementation

If you have a typed reference such as:

MyInterface foo

You can implement the entire interface using:

foo = {Object[] args -> println "This closure will be called by ALL methods"} as MyInterface

Alternatively, if you want to implement each method separately, you can use:

foo = [bar: {-> println "bar invoked"}, 
    baz: {param1 -> println "baz invoked with param $param1" ] as MyInterface
Don
+2  A: 

To intercept missing static methods use the following

 Foo {
    static A() { println "I'm A"}

     static $static_methodMissing(String name, args) {
        println "Missing static $name"
     }
 }

 Foo.A() -> "I'm A"
 Foo.B() -> "Missing static B"

-Ken

ken
New to Groovy, having a bit of difficulty parsing this.
ripper234
+1  A: 

You can convert a list to a map by using toSpreadMap(), convenient at times when the order in the list is enough to determine the keys and the values associated with them. See example below.

def list = ['key', 'value', 'foo', 'bar'] as Object[]
def map = list.toSpreadMap()

assert 2 == map.size()
assert 'value' == map.key
assert 'bar' == map['foo']
ken