Channels ▼
RSS

Web Development

Language of the Month: Groovy++, How Java and Groovy Can Be Better


Traits

Traits in Groovy++ are a powerful but simple tool for composition of functionality by small pieces. Technically speaking, a trait is a Java interface with default implementations for some methods.

When a non-abstract class implements such an interface, it can elect not to provide an implementation for these methods, in which case the default implementation will be used.

A trait falls between an interface and a class. It is like a class in that it includes implementation of some methods, and it is like an interface in that a class can implement any number of traits. Methods implemented in traits get mixed-in to classes that inherit from them.

Groovy++ traits are different (and possibly simpler) than Scala traits.

Listing Two is a simple example in which we define two traits (WithCoordinates and WithSize) and then subclass these traits in an class named Rectangle.

Listing Two: Using traits in Groovy++

@Typed package traits

@Trait class WithCoordinates {
   int x, y

   def moveTo (int newX, int newY) {
      x = newX
      y = newY
   }
}

@Trait class WithSize {
   int height, width

   def resize (int h, int w) {
      height = h
      width = w
   }
}

/* Rectangle inherits implementation from both traits */
class Rectangle implements WithCoordinates, WithSize {}

def r = new Rectangle()
r.resize(5, 10)
r.moveTo(2, 3)

Tail Recursion

Tail recursion is when a method calls itself, and the self-call occurs as the last call in the method. Tail recursion is important because it can be converted into iteration by a compiler. This allows you the expressiveness of a recursive call with the run-time behavior of iteration.

Here is classical example of tail recursion: a fast, recursive Fibbonacci calculation

long fib(int n, long s1 = 1, long s2 = 1) {
   n <= 1 ? s1 : fib(n-1, s1 + s2, s1 )
}

In Groovy++, the uses of tail recursion are somewhat limited by the abilities of the JVM, which does not natively support the construct. In Groovy++, tail recursive is supported with some small caveats: The call must use the same instance (this) or the method must be "effectively final," which means that the method cannot be overridden by a subclass, so it must be a:

  • static method
  • private method
  • final method
  • method of final class

Mutual tail recursion between two methods is not yet supported.

Mixing Dynamic and Static Code Together

By now you've started to think about Groovy++'s answer to the classic "should a programming language be statically or dynamically typed" question. There is no longer a clear separation between the two answers, as Groovy++ allows you to mix the two. We believe in using the right tool for the job, both approaches have value, and that the approaches can successfully be mixed.

Groovy++ allows developers to use annotations on parts or pieces of their code, and the annotations declare how these pieces should be compiled. You can annotate a single method, a whole class, or a whole file, and the annotations allow you to specify these compiler options:

  • statically typed
  • dynamically typed
  • typed in mixed mode

Mixed mode compilation in Groovy++ combines the performance and strictness of Groovy++ with the dynamic features of regular Groovy. So for example, you can mix markup builders (requiring metaprogramming) with calculations (requiring speed).

The idea is simple: If the static compiler is not able to resolve method call or property access statically, then instead of reporting an error (as it does in strict compilation mode), it immediately generates dynamic access to the method/property and assumes that the return value is of type java.lang.Object.

Listing Three illustrates the dynamic features of a Groovy MarkupBuilder to generate XML output and fast statically compiled code for fast calculations of divisors.

Listing Three: Using the Groovy MarkupBuilder

new MarkupBuilder ().numbers {
    def divisors = { int n, Collection alreadyFound = [] ->
        if (n > 3)
            for(candidate in 2..<n)
               if (n % candidate == 0)
                  return doCall (n / candidate, alreadyFound << candidate)

        alreadyFound << n
    }

    (2..1500).each {
      def divs = divisors(it) ]
      if (divs.size () == 1)
          number ([value: it, prime:true ])
      else {
          number ([value: it, prime:false]) {
            divs.each { div ->
              divisor([value: div])
            }
          }
      }
    }
}

This code generates something similar to

<numbers>
  <number value='2' prime='true' />
  <number value='3' prime='true' />
  <number value='4' prime='false'>
    <divisor value='2' />
    <divisor value='2' />
  </number>
  <number value='5' prime='true' />
  ...
<numbers>

Performance

One of the most important goals of Groovy++ is that compiled code run as fast as if it were written in Java. From time to time, we run a set of benchmarks to make sure this is a reality.

As you can see from Table 1, the results of benchmarks run on Groovy++ are very close to Java's speed. This table shows the tests performed on 26 April 2011. All times are in milliseconds (so smaller is better.)

[Click image to view at full size]
Table 1: Comparing Groovy++ performance with Groovy and Java.

Our main observations from these benchmarks are the following:

  • Groovy++ code is as fast as compiled Java
  • Groovy++ is many times faster than Groovy (even when compared with Groovy 1.8.0, which includes some substantial performance improvements)
  • Performance of pure Groovy can be unacceptably slow for some calculations and concurrent situations

Getting Started with Groovy++

Groovy++ is developed as an open source project under the liberal Apache License 2.0 — so you can download the binaries for immediate use, or build it from the sources.

When starting out with Groovy++, you'll find these links indispensable:

  1. Project Home: http://code.google.com/p/groovypptest/
  2. Mailing List: http://groups.google.com/group/groovyplusplus
  3. Source Repository: http://github.com/alextkachman/groovypp
  4. Defect Tracker: http://code.google.com/p/groovypptest/issues/

Groovy++ currently supports both stable versions of Groovy 1.7.10 and 1.8.0 For the instructions below, we assume you're installing Groovy++ v 0.4.231.

Downloading the binaries

Groovy++ can be downloaded here.

If you already have an existing Groovy setup, all you need is to download a single groovypp-<version>.jar and place it in your GROOVY_HOME\lib directory.

If you don't have an existing Groovy setup, you can download the complete groovypp-<version>.zip archive — it includes full a Groovy setup with groovypp-<version>.jar correctly placed. Just unpack it in a directory of your choice and point GROOVY_HOME to it.

Using Maven or Gradle

Groovy++ artifacts are deployed in the maven repository. The following snippet shows the maven dependency information that can be used to include Groovy++ in your project.

<dependency>
<groupid>org.codehaus.groovy</groupid>
	<artifactid>groovypp</artifactid>
	<version>0.4.231_1.8.0</version>
</dependency>

Windows installer for Groovy

Starting with Groovy 1.8.0, the Windows installer of Groovy includes Groovy++ 0.4.231

Conclusion

Groovy++ is powerful, fast programming language designed to be easy to learn for Java developers. It builds on both Groovy and Java by combining together statically and dynamically typed code, giving developers the best of both worlds. The result of using Groovy++ in a project is expressive and simple code along with the safety and speed of a statically compiled language. Enjoy!

— Alex Tkachman is the cofounder and COO of MBTE Sweden AB, the company behind both the Bindows framework and the Groovy++ programming language, which Alex created. Alex is core committer on Groovy project. He can be reached at alex.tkachman@gmail.com and @alextkachman on Twitter. Roshan Dawrani is a Groovy expert in MBTE Sweden AB and core committer on Groovy and Groovy++ projects. You can read his blog here. He can be reached at roshandawrani@gmail.com and @roshandawrani on Twitter.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV