Closure (Groovy 5.0.8)
Description: declaration: package: groovy.lang, class: Closure

Package groovy.lang

# Class Closure<V>

java.lang.Object
groovy.lang.GroovyObjectSupport
groovy.lang.Closure<V>

All Implemented Interfaces:
  `GroovyCallable<V>`, `GroovyObject`, `Serializable`, `Cloneable`, `Runnable`, `Callable<V>`

Direct Known Subclasses:
  `ComposedClosure`, `CurriedClosure`, `IteratorClosureAdapter`, `MethodClosure`

public abstract class Closure<V> extends GroovyObjectSupport implements Cloneable, Runnable, GroovyCallable<V>, 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

  Fields
  Modifier and Type
  Field
  Description
  `static final int`
  `DELEGATE_FIRST`
  With this resolveStrategy set the closure will attempt to resolve property references and methods to the delegate first then the owner.
  `static final int`
  `DELEGATE_ONLY`
  With this resolveStrategy set the closure will resolve property references and methods to the delegate only and entirely bypass the owner.
  `static final int`
  `DONE`
  `static final Closure`
  `IDENTITY`
  `protected int`
  `maximumNumberOfParameters`
  `static final int`
  `OWNER_FIRST`
  With this resolveStrategy set the closure will attempt to resolve property references and methods to the owner first, then the delegate (this is the default strategy).
  `static final int`
  `OWNER_ONLY`
  With this resolveStrategy set the closure will resolve property references and methods to the owner only and not call the delegate at all.
  `protected Class<?>[]`
  `parameterTypes`
  `static final int`
  `SKIP`
  `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.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `Closure(Object owner)`
  Constructor used when the "this" object for the Closure is null.
  `Closure(Object owner, Object thisObject)`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `<W> Closure<W>`
  `andThen(Closure<W> other)`
  Alias for `rightShift(Closure)`
  `Closure<V>`
  `andThenSelf()`
  Call `andThen(Closure)` on `this`.
  `Closure<V>`
  `andThenSelf(int times)`
  Call `andThen(Closure)` on `this` exactly `times` times.
  `Closure`
  `asWritable()`
  `V`
  `call()`
  Invokes the closure with no arguments, returning any value if applicable.
  `V`
  `call(Object arguments)`
  Invokes the closure with given argument(s), returning any value if applicable.
  `V`
  `call(Object... arguments)`
  Invokes the closure with given argument(s), returning any value if applicable.
  `Object`
  `clone()`
  `Closure<V>`
  `compose(Closure other)`
  Alias for `leftShift(Closure)`
  `Closure<V>`
  `composeSelf()`
  Call `compose(Closure)` on `this`.
  `Closure<V>`
  `composeSelf(int times)`
  Call `compose(Closure)` on `this` exactly `times` times.
  `Closure<V>`
  `curry(Object argument)`
  Support for Closure currying.
  `Closure<V>`
  `curry(Object... arguments)`
  Support for Closure currying.
  `Closure<V>`
  `dehydrate()`
  Returns a copy of this closure where the "owner", "delegate" and "thisObject" fields are null, allowing proper serialization when one of them is not serializable.
  `Object`
  `getDelegate()`
  `int`
  `getDirective()`
  `int`
  `getMaximumNumberOfParameters()`
  `Object`
  `getOwner()`
  `Class<?>[]`
  `getParameterTypes()`
  `Object`
  `getProperty(String property)`
  Retrieves a property value.
  `int`
  `getResolveStrategy()`
  Gets the strategy which the closure uses to resolve methods and properties
  `Object`
  `getThisObject()`
  `boolean`
  `isCase(Object switchValue)`
  `Closure<V>`
  `leftShift(Closure other)`
  Support for Closure reverse composition.
  `V`
  `leftShift(Object arg)`
  Alias for calling a Closure for non-closure arguments.
  `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, Object argument)`
  Support for Closure currying at a given index.
  `Closure<V>`
  `ncurry(int n, Object... arguments)`
  Support for Closure currying at a given index.
  `Closure<V>`
  `rcurry(Object argument)`
  Support for Closure "right" currying.
  `Closure<V>`
  `rcurry(Object... arguments)`
  Support for Closure "right" currying.
  `Closure<V>`
  `rehydrate(Object delegate, Object owner, Object thisObject)`
  Returns a copy of this closure for which the delegate, owner and thisObject are replaced with the supplied parameters.
  `<W> Closure<W>`
  `rightShift(Closure<W> other)`
  Support for Closure forward composition.
  `void`
  `run()`
  `void`
  `setDelegate(Object delegate)`
  Allows the delegate to be changed such as when performing markup building
  `void`
  `setDirective(int directive)`
  `void`
  `setProperty(String property, 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 and methods.
  `protected static Object`
  `throwRuntimeException(Throwable throwable)`
  `Closure<V>`
  `trampoline()`
  Builds a trampolined variant of the current closure.
  `Closure<V>`
  `trampoline(Object... args)`
  Builds a trampolined variant of the current closure.

  ### Methods inherited from class groovy.lang.GroovyObjectSupport

  `getMetaClass, setMetaClass`

  ### Methods inherited from class java.lang.Object

  `equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

  ### Methods inherited from interface groovy.lang.GroovyObject

  `invokeMethod`

- ## Field Details

  - ### OWNER_FIRST

    public static final int OWNER_FIRST
    With this resolveStrategy set the closure will attempt to resolve property references and methods 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()
                 assert x == 30
                 assert y == 70
                 assert data == [x:10, y:20]
             }
         }

         new Test().run()

    Will succeed, because the x and y fields declared in the Test class shadow 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 and methods 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()
                 assert x == 30
                 assert y == 40
                 assert data == [x:10, y:30]
             }
         }

         new Test().run()

    This will succeed, 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 and methods 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 + z }
                 cl.delegate = data
                 cl.resolveStrategy = Closure.OWNER_ONLY
                 cl()
                 println x
                 println y
                 println data
             }
         }

         groovy.test.GroovyAssert.shouldFail(MissingPropertyException) {
             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 and methods 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
             }
         }

         groovy.test.GroovyAssert.shouldFail {
             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 and methods 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 Class<?>[] parameterTypes

  - ### maximumNumberOfParameters

    protected int maximumNumberOfParameters

- ## Constructor Details

  - ### Closure

    public Closure(Object owner, Object thisObject)

  - ### Closure

    public Closure(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 Details

  - ### setResolveStrategy

    public void setResolveStrategy(int resolveStrategy)
    Sets the strategy which the closure uses to resolve property references and methods. 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 uses to resolve methods and properties
    Returns:
      The resolve strategy
    See Also:
      - `DELEGATE_FIRST`
      - `DELEGATE_ONLY`
      - `OWNER_FIRST`
      - `OWNER_ONLY`
      - `TO_SELF`

  - ### getThisObject

    public Object getThisObject()

  - ### getProperty

    public Object getProperty(String property)
    Description copied from interface: `GroovyObject`
    Retrieves a property value.
    Specified by:
      `getProperty` in interface `GroovyObject`
    Parameters:
      `property` - the name of the property of interest
    Returns:
      the given property

  - ### setProperty

    public void setProperty(String property, Object newValue)
    Description copied from interface: `GroovyObject`
    Sets the given property to the new value.
    Specified by:
      `setProperty` in interface `GroovyObject`
    Parameters:
      `property` - the name of the property of interest
      `newValue` - the new value for the property

  - ### isCase

    public boolean isCase(Object switchValue)

  - ### call

    public V call()
    Invokes the closure with no arguments, returning any value if applicable.
    Specified by:
      `call` in interface `Callable<V>`
    Returns:
      The value if applicable or null if there is no return statement in the closure.

  - ### call

    public V call(Object arguments)
    Invokes the closure with given argument(s), 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.

  - ### call

    public V call(Object... arguments)
    Invokes the closure with given argument(s), returning any value if applicable.
    Returns:
      The value if applicable or null if there is no return statement in the closure.

  - ### throwRuntimeException

    protected static Object throwRuntimeException(Throwable throwable)

  - ### getOwner

    public 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 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(Object delegate)
    Allows the delegate to be changed such as when performing markup building
    Parameters:
      `delegate` - the new delegate

  - ### getParameterTypes

    public 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 `Runnable`

  - ### curry

    public Closure<V> curry(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

  - ### curry

    public Closure<V> curry(Object argument)
    Support for Closure currying.
    Parameters:
      `argument` - the argument to bind
    Returns:
      the new closure with the argument bound
    See Also:
      - `curry(Object...)`

  - ### rcurry

    public Closure<V> rcurry(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

    The position of the curried parameters will be calculated lazily, for example, if two overloaded doCall methods are available, the supplied arguments plus the curried arguments will be concatenated and the result used for method selection.
    Parameters:
      `arguments` - the arguments to bind
    Returns:
      the new closure with its arguments bound
    See Also:
      - `curry(Object...)`

  - ### rcurry

    public Closure<V> rcurry(Object argument)
    Support for Closure "right" currying.
    Parameters:
      `argument` - the argument to bind
    Returns:
      the new closure with the argument bound
    See Also:
      - `rcurry(Object...)`

  - ### ncurry

    public Closure<V> ncurry(int n, 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

    The position of the curried parameters will be calculated eagerly and implies all arguments prior to the specified n index are supplied. Default parameter values prior to the n index will not be available.
    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...)`

  - ### ncurry

    public Closure<V> ncurry(int n, Object argument)
    Support for Closure currying at a given index.
    Parameters:
      `argument` - the argument to bind
    Returns:
      the new closure with the argument bound
    See Also:
      - `ncurry(int, Object...)`

  - ### rightShift

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

    Typical usage:

         def times2 = { a -> a * 2 }
         def add3 = { a -> a + 3 }
         def timesThenAdd = times2 >> add3
         // equivalent: timesThenAdd = { a -> add3(times2(a)) }
         assert timesThenAdd(3) == 9

    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 times2 = { a -> a * 2 }
         def add3 = { a -> a + 3 }
         def addThenTimes = times2 << add3
         // equivalent: addThenTimes = { a -> times2(add3(a)) }
         assert addThenTimes(3) == 12

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

  - ### andThen

    public <W> Closure<W> andThen(Closure<W> other)
    Alias for `rightShift(Closure)`
    Returns:
      the newly composed closure

  - ### andThenSelf

    public Closure<V> andThenSelf()
    Call `andThen(Closure)` on `this`.
    Returns:
      the newly composed closure

  - ### andThenSelf

    public Closure<V> andThenSelf(int times)
    Call `andThen(Closure)` on `this` exactly `times` times.
    Parameters:
      `times` - the number of times to reverse compose the closure with itself
    Returns:
      the newly composed closure

  - ### compose

    public Closure<V> compose(Closure other)
    Alias for `leftShift(Closure)`
    Returns:
      the newly composed closure

  - ### composeSelf

    public Closure<V> composeSelf()
    Call `compose(Closure)` on `this`.
    Returns:
      the newly composed closure

  - ### composeSelf

    public Closure<V> composeSelf(int times)
    Call `compose(Closure)` on `this` exactly `times` times.
    Parameters:
      `times` - the number of times to compose the closure with itself
    Returns:
      the newly composed closure

  - ### leftShift

    public V leftShift(Object arg)
    Alias for calling a Closure for non-closure arguments.

    Typical usage:

         def times2 = { a -> a * 2 }
         def add3 = { a -> a + 3 }
         assert add3 << times2 << 3 == 9

    Parameters:
      `arg` - the argument to call the closure with
    Returns:
      the result of calling the Closure

  - ### 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(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 returns 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 returns 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 Object clone()
    Overrides:
      `clone` in class `Object`

  - ### getDirective

    public int getDirective()
    Returns:
      Returns the directive.

  - ### setDirective

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

  - ### dehydrate

    public Closure<V> dehydrate()
    Returns a copy of this closure where the "owner", "delegate" and "thisObject" fields are null, allowing proper serialization when one of them is not serializable.
    Returns:
      a serializable closure.
    Since:
      1.8.5

  - ### rehydrate

    public Closure<V> rehydrate(Object delegate, Object owner, Object thisObject)
    Returns a copy of this closure for which the delegate, owner and thisObject are replaced with the supplied parameters. Use this when you want to rehydrate a closure which has been made serializable thanks to the `dehydrate()` method.
    Parameters:
      `delegate` - the closure delegate
      `owner` - the closure owner
      `thisObject` - the closure "this" object
    Returns:
      a copy of this closure where owner, delegate and thisObject are replaced
    Since:
      1.8.5