How can I call the label
function and set a closure to it as the last parameter in this way? This code works only if I call label
with parentheses but I don't need them. Is it possible to set the closure into function without them?
label = { name, callback ->
callback()
}
label "lbl" { // not works
println "call $it"
}
label ("lbl") { // works
println "call $it"
}
It is used to separate where you declare bindings for your closure from the actual code, eg: def myClosure = { x, y -> x + y } the part before -> declares that the closure has two arguments named x and y while the second part is the code of the closure.
A closure is an anonymous block of code.
A closure is a short anonymous block of code. It just normally spans a few lines of code. A method can even take the block of code as a parameter. They are anonymous in nature.
If you don't want to use parentheses then you have to split closure arguments with ,
to tell the compiler that you want to execute label
with following two parameters:
label "lbl", {
println "call $it"
}
This notation is equivalent of:
label("lbl", {
println "call $it"
})
Groovy has this syntactic sugar that allows you passing closure outside parenthesis when closure is the last parameter of a function prototype, that's why following notation works:
label ("lbl") {
println "call $it"
}
But it is still an equivalent of the ones mentioned earlier.
How to make
label "lbl" { }
a valid statement?If you really want to compile code like:
label "lbl" { println "call $it" }
you need to be aware of one thing - such notation is an equivalent of:
label("lbl" { println "call $it" })
It means that there is a function
label
that accepts single parameter - a value returned fromlbl
function that accepts a single parameter - closure. The implementation of these functions might look like this:def label = { value -> // do something with value println "The value accepted by label function is '${value}'" } def lbl = { callback -> callback?.call() } label "lbl" { println "call $it" }
It compiles and it prints following output to console:
call null The value accepted by label function is 'null'
Of course as you can see you have to implement method
lbl
and in most cases this is very limiting - you can't calllabel
function with any parameter different thanlbl
. You could implement Groovy'smethodMissing(name, args)
function that gets called whenever non-existing method gets invoked. Consider following example:def methodMissing(String name, args) { if (args.length == 1 && args[0] instanceof Closure) { println "Running missing method '${name}'" return args[0].call() } throw new MissingMethodException(name, this.class, args) } def label = { value -> // do something with value println "The value accepted by label function is '${value}'" } def lbl = { callback -> callback?.call() } label "lbl" { println "call $it" } label "test" { println "nothing" }
In this case when
label "test" { println "nothing" }
gets invoked, Groovy usesmissingMethod
because methodtest
does not exist in the runtime context.call null The value accepted by label function is 'null' Running missing method 'test' nothing The value accepted by label function is 'null'
However it doesn't mean, that you can think about this as an equivalent of getting rid of coma separator or parenthesis from your code. This is an example of a simple DSL written with Groovy that uses
methodMissing
mechanism to satisfy non-existing methods invocation. This last example is actually the same as:label("test" { println "nothing" })
A function that expects a single argument and in this case we provide it as a result of
test
method invocation with a single parameter{ println "nothing" }
.I would strongly suggest accepting the fact that Groovy requires you to separate function arguments with a coma and don't use such DSL to remove coma or parenthesis from the code. Groovy DSL is very powerful and you have to know what you are doing when you decide using this tool in your code. For instance, think about what happens if you call:
label "test" { println "something" }
and for some reason a method defined as a following closure:
def test = { int num -> num + 2 }
exists in your class. You will start getting exceptions, because
methodMissing
is not called anymore in this case. Methodtest
exists, but it does not have a signature that accepts a single closure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With