groovy.lang
Class Closure<V>

java.lang.Object
  extended by groovy.lang.GroovyObjectSupport
      extended by groovy.lang.Closure<V>
All Implemented Interfaces:
GroovyCallable<V>, GroovyObject, java.io.Serializable, java.lang.Cloneable, java.lang.Runnable, java.util.concurrent.Callable<V>
Direct Known Subclasses:
ComposedClosure, CurriedClosure, IteratorClosureAdapter, MethodClosure, NumberRangeTest.RecordingClosure

public abstract class Closure<V>
extends GroovyObjectSupport
implements java.lang.Cloneable, java.lang.Runnable, GroovyCallable<V>, java.io.Serializable

Represents any closure object in Groovy.

Groovy allows instances of Closures to be called in a short form. For example:

   def a = 1
   def c = {a}
   assert c() == 1
 
To be able to use a Closure in this way with your own subclass, you need to provide a doCall method with any signature you want to. This ensures that getMaximumNumberOfParameters() and getParameterTypes() will work too without any additional code. If no doCall method is provided a closure must be used in its long form like
   def a = 1
   def c = {a}
   assert c.call() == 1
 

See Also:
Serialized Form

Field Summary
static int DELEGATE_FIRST
          With this resolveStrategy set the closure will attempt to resolve property references to the delegate first then the owner.
static int DELEGATE_ONLY
          With this resolveStrategy set the closure will resolve property references to the delegate only and entirely bypass the owner.
static int DONE
           
static Closure IDENTITY
           
protected  int maximumNumberOfParameters
           
static int OWNER_FIRST
          With this resolveStrategy set the closure will attempt to resolve property references to the owner first, then the delegate (this is the default strategy).
static int OWNER_ONLY
          With this resolveStrategy set the closure will resolve property references to the owner only and not call the delegate at all.
protected  java.lang.Class[] parameterTypes
           
static int SKIP
           
static int TO_SELF
          With this resolveStrategy set the closure will resolve property references to itself and go through the usual MetaClass look-up process.
 
Constructor Summary
Closure(java.lang.Object owner)
          Constructor used when the "this" object for the Closure is null.
Closure(java.lang.Object owner, java.lang.Object thisObject)
           
 
Method Summary
 Closure asWritable()
           
 V call()
          Invokes the closure without any parameters, returning any value if applicable.
 V call(java.lang.Object... args)
           
 V call(java.lang.Object arguments)
          Invokes the closure, returning any value if applicable.
 java.lang.Object clone()
           
 Closure<V> curry(java.lang.Object... arguments)
          Support for Closure currying.
 java.lang.Object getDelegate()
           
 int getDirective()
           
 int getMaximumNumberOfParameters()
           
 java.lang.Object getOwner()
           
 java.lang.Class[] getParameterTypes()
           
 java.lang.Object getProperty(java.lang.String property)
          Retrieves a property value.
 int getResolveStrategy()
          Gets the strategy which the closure users to resolve methods and properties
 java.lang.Object getThisObject()
           
 boolean isCase(java.lang.Object candidate)
           
 Closure<V> leftShift(Closure other)
          Support for Closure reverse composition.
 V leftShift(java.lang.Object arg)
           
 Closure<V> memoize()
          Creates a caching variant of the closure.
 Closure<V> memoizeAtLeast(int protectedCacheSize)
          Creates a caching variant of the closure with automatic cache size adjustment and lower limit on the cache size.
 Closure<V> memoizeAtMost(int maxCacheSize)
          Creates a caching variant of the closure with upper limit on the cache size.
 Closure<V> memoizeBetween(int protectedCacheSize, int maxCacheSize)
          Creates a caching variant of the closure with automatic cache size adjustment and lower and upper limits on the cache size.
 Closure<V> ncurry(int n, java.lang.Object... arguments)
          Support for Closure currying at a given index.
 Closure<V> rcurry(java.lang.Object... arguments)
          Support for Closure "right" currying.
<W> Closure<W>
rightShift(Closure<W> other)
          Support for Closure forward composition.
 void run()
           
 void setDelegate(java.lang.Object delegate)
          Allows the delegate to be changed such as when performing markup building
 void setDirective(int directive)
           
 void setProperty(java.lang.String property, java.lang.Object newValue)
          Sets the given property to the new value.
 void setResolveStrategy(int resolveStrategy)
          Sets the strategy which the closure uses to resolve property references.
protected static java.lang.Object throwRuntimeException(java.lang.Throwable throwable)
           
 Closure<V> trampoline()
          Builds a trampolined variant of the current closure.
 Closure<V> trampoline(java.lang.Object... args)
          Builds a trampolined variant of the current closure.
 
Methods inherited from class groovy.lang.GroovyObjectSupport
getMetaClass, invokeMethod, setMetaClass
 
Methods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

OWNER_FIRST

public static final int OWNER_FIRST
With this resolveStrategy set the closure will attempt to resolve property references to the owner first, then the delegate (this is the default strategy). For example the following code :
  class Test {
    def x = 30
    def y = 40

    def run() {
        def data = [ x: 10, y: 20 ]
        def cl = { y = x + y }
        cl.delegate = data
        cl()
        println x
        println y
        println data
    }
  }

  new Test().run()
 
will output :
     30
     70
     [x:10, y:20]
 
because the x and y fields declared in the Test class the variables in the delegate.

Note that local variables are always looked up first, independently of the resolution strategy.

See Also:
Constant Field Values

DELEGATE_FIRST

public static final int DELEGATE_FIRST
With this resolveStrategy set the closure will attempt to resolve property references to the delegate first then the owner. For example the following code :
  class Test {
    def x = 30
    def y = 40

    def run() {
        def data = [ x: 10, y: 20 ]
        def cl = { y = x + y }
        cl.delegate = data
        cl.resolveStrategy = Closure.DELEGATE_FIRST
        cl()
        println x
        println y
        println data
    }
  }

  new Test().run()
 
will output :
     30
     40
     [x:10, y:30]
 
because the x and y variables declared in the delegate shadow the fields in the owner class.

Note that local variables are always looked up first, independently of the resolution strategy.

See Also:
Constant Field Values

OWNER_ONLY

public static final int OWNER_ONLY
With this resolveStrategy set the closure will resolve property references to the owner only and not call the delegate at all. For example the following code :
  class Test {
    def x = 30
    def y = 40

    def run() {
        def data = [ x: 10, y: 20, z: 30 ]
        def cl = { y = x + y }
        cl.delegate = data
        cl.resolveStrategy = Closure.OWNER_ONLY
        cl()
        println x
        println y
        println data
    }
  }

  new Test().run()
 
will throw "No such property: z" error because even if the z variable is declared in the delegate, no lookup is made.

Note that local variables are always looked up first, independently of the resolution strategy.

See Also:
Constant Field Values

DELEGATE_ONLY

public static final int DELEGATE_ONLY
With this resolveStrategy set the closure will resolve property references to the delegate only and entirely bypass the owner. For example the following code :
  class Test {
    def x = 30
    def y = 40
    def z = 50

    def run() {
        def data = [ x: 10, y: 20 ]
        def cl = { y = x + y + z}
        cl.delegate = data
        cl.resolveStrategy = Closure.DELEGATE_ONLY
        cl()
        println x
        println y
        println data
    }
  }

  new Test().run()
 
will throw an error because even if the owner declares a "z" field, the resolution strategy will bypass lookup in the owner.

Note that local variables are always looked up first, independently of the resolution strategy.

See Also:
Constant Field Values

TO_SELF

public static final int TO_SELF
With this resolveStrategy set the closure will resolve property references to itself and go through the usual MetaClass look-up process. This means that properties are neither resolved from the owner nor the delegate, but only on the closure object itself. This allows the developer to override getProperty using ExpandoMetaClass of the closure itself.

Note that local variables are always looked up first, independently of the resolution strategy.

See Also:
Constant Field Values

DONE

public static final int DONE
See Also:
Constant Field Values

SKIP

public static final int SKIP
See Also:
Constant Field Values

IDENTITY

public static final Closure IDENTITY

parameterTypes

protected java.lang.Class[] parameterTypes

maximumNumberOfParameters

protected int maximumNumberOfParameters
Constructor Detail

Closure

public Closure(java.lang.Object owner,
               java.lang.Object thisObject)

Closure

public Closure(java.lang.Object owner)
Constructor used when the "this" object for the Closure is null. This is rarely the case in normal Groovy usage.

Parameters:
owner - the Closure owner
Method Detail

setResolveStrategy

public void setResolveStrategy(int resolveStrategy)
Sets the strategy which the closure uses to resolve property references. The default is Closure.OWNER_FIRST

Parameters:
resolveStrategy - The resolve strategy to set
See Also:
DELEGATE_FIRST, DELEGATE_ONLY, OWNER_FIRST, OWNER_ONLY, TO_SELF

getResolveStrategy

public int getResolveStrategy()
Gets the strategy which the closure users to resolve methods and properties

Returns:
The resolve strategy
See Also:
DELEGATE_FIRST, DELEGATE_ONLY, OWNER_FIRST, OWNER_ONLY, TO_SELF

getThisObject

public java.lang.Object getThisObject()

getProperty

public java.lang.Object getProperty(java.lang.String property)
Description copied from interface: GroovyObject
Retrieves a property value.

Specified by:
getProperty in interface GroovyObject
Overrides:
getProperty in class GroovyObjectSupport
Parameters:
property - the name of the property of interest
Returns:
the given property

setProperty

public void setProperty(java.lang.String property,
                        java.lang.Object newValue)
Description copied from interface: GroovyObject
Sets the given property to the new value.

Specified by:
setProperty in interface GroovyObject
Overrides:
setProperty in class GroovyObjectSupport
Parameters:
property - the name of the property of interest
newValue - the new value for the property

isCase

public boolean isCase(java.lang.Object candidate)

call

public V call()
Invokes the closure without any parameters, returning any value if applicable.

Specified by:
call in interface java.util.concurrent.Callable<V>
Returns:
the value if applicable or null if there is no return statement in the closure

call

public V call(java.lang.Object... args)

call

public V call(java.lang.Object arguments)
Invokes the closure, returning any value if applicable.

Parameters:
arguments - could be a single value or a List of values
Returns:
the value if applicable or null if there is no return statement in the closure

throwRuntimeException

protected static java.lang.Object throwRuntimeException(java.lang.Throwable throwable)

getOwner

public java.lang.Object getOwner()
Returns:
the owner Object to which method calls will go which is typically the outer class when the closure is constructed

getDelegate

public java.lang.Object getDelegate()
Returns:
the delegate Object to which method calls will go which is typically the outer class when the closure is constructed

setDelegate

public void setDelegate(java.lang.Object delegate)
Allows the delegate to be changed such as when performing markup building

Parameters:
delegate - the new delegate

getParameterTypes

public java.lang.Class[] getParameterTypes()
Returns:
the parameter types of the longest doCall method of this closure

getMaximumNumberOfParameters

public int getMaximumNumberOfParameters()
Returns:
the maximum number of parameters a doCall method of this closure can take

asWritable

public Closure asWritable()
Returns:
a version of this closure which implements Writable. Note that the returned Writable also overrides Object.toString() in order to allow rendering the result directly to a String.

run

public void run()
Specified by:
run in interface java.lang.Runnable

curry

public Closure<V> curry(java.lang.Object... arguments)
Support for Closure currying.

Typical usage:

 def multiply = { a, b -> a * b }
 def doubler = multiply.curry(2)
 assert doubler(4) == 8
 
Note: special treatment is given to Closure vararg-style capability. If you curry a vararg parameter, you don't consume the entire vararg array but instead the first parameter of the vararg array as the following example shows:
 def a = { one, two, Object[] others -> one + two + others.sum() }
 assert a.parameterTypes.name == ['java.lang.Object', 'java.lang.Object', '[Ljava.lang.Object;']
 assert a(1,2,3,4) == 10
 def b = a.curry(1)
 assert b.parameterTypes.name == ['java.lang.Object', '[Ljava.lang.Object;']
 assert b(2,3,4) == 10
 def c = b.curry(2)
 assert c.parameterTypes.name == ['[Ljava.lang.Object;']
 assert c(3,4) == 10
 def d = c.curry(3)
 assert d.parameterTypes.name == ['[Ljava.lang.Object;']
 assert d(4) == 10
 def e = d.curry(4)
 assert e.parameterTypes.name == ['[Ljava.lang.Object;']
 assert e() == 10
 assert e(5) == 15
 

Parameters:
arguments - the arguments to bind
Returns:
the new closure with its arguments bound

rcurry

public Closure<V> rcurry(java.lang.Object... arguments)
Support for Closure "right" currying. Parameters are supplied on the right rather than left as per the normal curry() method. Typical usage:
 def divide = { a, b -> a / b }
 def halver = divide.rcurry(2)
 assert halver(8) == 4
 

Parameters:
arguments - the arguments to bind
Returns:
the new closure with its arguments bound
See Also:
curry(Object...)

ncurry

public Closure<V> ncurry(int n,
                         java.lang.Object... arguments)
Support for Closure currying at a given index. Parameters are supplied from index position "n". Typical usage:
 def caseInsensitive = { a, b -> a.toLowerCase() <=> b.toLowerCase() } as Comparator
 def caseSensitive = { a, b -> a <=> b } as Comparator
 def animals1 = ['ant', 'dog', 'BEE']
 def animals2 = animals1 + ['Cat']
 // curry middle param of this utility method:
 // Collections#binarySearch(List list, Object key, Comparator c)
 def catSearcher = Collections.&binarySearch.ncurry(1, "cat")
 [[animals1, animals2], [caseInsensitive, caseSensitive]].combinations().each{ a, c ->
   def idx = catSearcher(a.sort(c), c)
   print a.sort(c).toString().padRight(22)
   if (idx < 0) println "Not found but would belong in position ${-idx - 1}"
   else println "Found at index $idx"
 }
 // =>
 // [ant, BEE, dog]       Not found but would belong in position 2
 // [ant, BEE, Cat, dog]  Found at index 2
 // [BEE, ant, dog]       Not found but would belong in position 2
 // [BEE, Cat, ant, dog]  Not found but would belong in position 3
 

Parameters:
n - the index from which to bind parameters (may be -ve in which case it will be normalized)
arguments - the arguments to bind
Returns:
the new closure with its arguments bound
See Also:
curry(Object...)

rightShift

public <W> Closure<W> rightShift(Closure<W> other)
Support for Closure forward composition.

Typical usage:

 def twice = { a -> a * 2 }
 def thrice = { a -> a * 3 }
 def times6 = twice >> thrice
 // equivalent: times6 = { a -> thrice(twice(a)) }
 assert times6(3) == 18
 

Parameters:
other - the Closure to compose with the current Closure
Returns:
the new composed Closure

leftShift

public Closure<V> leftShift(Closure other)
Support for Closure reverse composition.

Typical usage:

 def twice = { a -> a * 2 }
 def thrice = { a -> a * 3 }
 def times6 = thrice << twice
 // equivalent: times6 = { a -> thrice(twice(a)) }
 assert times6(3) == 18
 

Parameters:
other - the Closure to compose with the current Closure
Returns:
the new composed Closure

leftShift

public V leftShift(java.lang.Object arg)

memoize

public Closure<V> memoize()
Creates a caching variant of the closure. Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache making subsequent calls with the same arguments fast. This variant will keep all cached values forever, i.e. till the closure gets garbage-collected. The returned function can be safely used concurrently from multiple threads, however, the implementation values high average-scenario performance and so concurrent calls on the memoized function with identical argument values may not necessarily be able to benefit from each other's cached return value. With this having been mentioned, the performance trade-off still makes concurrent use of memoized functions safe and highly recommended. The cache gets garbage-collected together with the memoized closure.

Returns:
A new closure forwarding to the original one while caching the results

memoizeAtMost

public Closure<V> memoizeAtMost(int maxCacheSize)
Creates a caching variant of the closure with upper limit on the cache size. Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache making subsequent calls with the same arguments fast. This variant will keep all values until the upper size limit is reached. Then the values in the cache start rotating using the LRU (Last Recently Used) strategy. The returned function can be safely used concurrently from multiple threads, however, the implementation values high average-scenario performance and so concurrent calls on the memoized function with identical argument values may not necessarily be able to benefit from each other's cached return value. With this having been mentioned, the performance trade-off still makes concurrent use of memoized functions safe and highly recommended. The cache gets garbage-collected together with the memoized closure.

Parameters:
maxCacheSize - The maximum size the cache can grow to
Returns:
A new function forwarding to the original one while caching the results

memoizeAtLeast

public Closure<V> memoizeAtLeast(int protectedCacheSize)
Creates a caching variant of the closure with automatic cache size adjustment and lower limit on the cache size. Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache making subsequent calls with the same arguments fast. This variant allows the garbage collector to release entries from the cache and at the same time allows the user to specify how many entries should be protected from the eventual gc-initiated eviction. Cached entries exceeding the specified preservation threshold are made available for eviction based on the LRU (Last Recently Used) strategy. Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the limits set by the user if memory is plentiful. The returned function can be safely used concurrently from multiple threads, however, the implementation values high average-scenario performance and so concurrent calls on the memoized function with identical argument values may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter might not be respected accurately in such scenarios for some periods of time. With this having been mentioned, the performance trade-off still makes concurrent use of memoized functions safe and highly recommended. The cache gets garbage-collected together with the memoized closure.

Parameters:
protectedCacheSize - Number of cached return values to protect from garbage collection
Returns:
A new function forwarding to the original one while caching the results

memoizeBetween

public Closure<V> memoizeBetween(int protectedCacheSize,
                                 int maxCacheSize)
Creates a caching variant of the closure with automatic cache size adjustment and lower and upper limits on the cache size. Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache making subsequent calls with the same arguments fast. This variant allows the garbage collector to release entries from the cache and at the same time allows the user to specify how many entries should be protected from the eventual gc-initiated eviction. Cached entries exceeding the specified preservation threshold are made available for eviction based on the LRU (Last Recently Used) strategy. Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the protected size limits set by the user, if memory is plentiful. Also, this variant will never exceed in size the upper size limit. Once the upper size limit has been reached, the values in the cache start rotating using the LRU (Last Recently Used) strategy. The returned function can be safely used concurrently from multiple threads, however, the implementation values high average-scenario performance and so concurrent calls on the memoized function with identical argument values may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter might not be respected accurately in such scenarios for some periods of time. With this having been mentioned, the performance trade-off still makes concurrent use of memoized functions safe and highly recommended. The cache gets garbage-collected together with the memoized closure.

Parameters:
protectedCacheSize - Number of cached return values to protect from garbage collection
maxCacheSize - The maximum size the cache can grow to
Returns:
A new function forwarding to the original one while caching the results

trampoline

public Closure<V> trampoline(java.lang.Object... args)
Builds a trampolined variant of the current closure. To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of the calculation and, instead of a recursive call to itself or another function, it return back a new closure, which will be executed by the trampoline as the next step. Once a non-closure value is returned, the trampoline stops and returns the value as the final result. Here is an example:
 def fact
 fact = { n, total ->
     n == 0 ? total : fact.trampoline(n - 1, n * total)
 }.trampoline()
 def factorial = { n -> fact(n, 1G)}
 println factorial(20) // => 2432902008176640000
 

Parameters:
args - Parameters to the closure, so as the trampoline mechanism can call it
Returns:
A closure, which will execute the original closure on a trampoline.

trampoline

public Closure<V> trampoline()
Builds a trampolined variant of the current closure. To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of the calculation and, instead of a recursive call to itself or another function, it return back a new closure, which will be executed by the trampoline as the next step. Once a non-closure value is returned, the trampoline stops and returns the value as the final result.

Returns:
A closure, which will execute the original closure on a trampoline.
See Also:
trampoline(Object...)

clone

public java.lang.Object clone()
Overrides:
clone in class java.lang.Object

getDirective

public int getDirective()
Returns:
Returns the directive.

setDirective

public void setDirective(int directive)
Parameters:
directive - The directive to set.