This took me awhile to wrap my head around this as well. Keep in mind what
Guillaume said, the object passed to the closure is a writer. This example
should hopefully make it clearer what is going on:
a = {
println x.class
x -> println x
x.write('foo')
return 'bar'
}
assert "no argument ${a}" == "no argument foo"
This will print "class java.io.StringWriter" to System.out
Since the parameter passed to the closure is a StringWriter 'println x' will
cause Groovy to call toString() on the writer, which already contains the
string "no argument ". The string 'foo' is then appended to the writer so the
GString finally resolves to "no argument foo". Notice the return value from
the closure is ignored.
Hope this helps,
Keith
> On Jan 21, 2017, at 12:54 PM, Anthony Hepple <[email protected]>
> wrote:
>
> Hi Yang
>
> I too am confused. The following code better describes my confusion:
>
> a = {x -> println x}
> assert "no argument ${a}" == "no argument "
>
> So far so good, but why does this have the side effect of printing "no
> argument" to standard out? As you say, the closure, a, appears to
> magically capture the string "no argument".
>
> Perhaps if someone could explain this they would help us both?
>
> Thanks
> Anthony
>
> On 21 January 2017 at 16:19, Guillaume Laforge <[email protected]> wrote:
>> x doesn't capture the value "a".
>> Your GString contains a "a", and when you call a() you pass the string "a"
>> to it.
>> So the a() call return "a", and you print "a", so you see the output as well
>> as the println of "a", thus two "a"'s.
>>
>> Not sure how you came with that code. It's pretty confusing.
>> Normally, if you use a one-arg closure inside a GString, the parameter of
>> the closure is actually a writer against which you can write. You're not
>> supposed to print from there or have side effects.
>>
>> What are you trying to achieve here?
>>
>> Guillaume
>>
>> On Sat, Jan 21, 2017 at 4:46 AM, Yang Yang <[email protected]> wrote:
>>>
>>> Sorry, after reading that part of documentation I still feel a bit
>>> confused.
>>>
>>> groovy:000> "a${x->println x}"
>>> a
>>> a
>>> ===> a
>>> groovy:000> a = {x->println x}
>>> ===> groovysh_evaluate$_run_closure1@737a135b
>>> groovy:000> a("a${x->println x}")
>>> a
>>> a
>>> ===> null
>>>
>>> Say "a${a}" will be expanded as "a${x->println x}" and I don't understand
>>> why x captured the value "a" ?
>>>
>>> "a${x->println x}" will output "a" because ${x->println x} will be lazy
>>> evaluated. Then the result "a" is magically captured by the closure
>>> {x->println x} and it print another "a". But if it like so then the first
>>> return ===> should be null.
>>>
>>>
>>>
>>> On 20 Jan 2017, at 16:49, Guillaume Laforge <[email protected]> wrote:
>>>
>>> Hi Yang,
>>>
>>> Interpolated values in a GString that are closures are executed.
>>> Have a look at the documentation which shows some examples of this:
>>>
>>> http://groovy-lang.org/syntax.html#_special_case_of_interpolating_closure_expressions
>>>
>>> Guillaume
>>>
>>>
>>> On Fri, Jan 20, 2017 at 8:22 AM, Yang Yang <[email protected]> wrote:
>>>>
>>>> Script:
>>>> a = {x -> println x}
>>>> a("a${a}")
>>>>
>>>> Output:
>>>> a
>>>> a
>>>>
>>>> Why?
>>>
>>>
>>>
>>>
>>> --
>>> Guillaume Laforge
>>> Apache Groovy committer & PMC Vice-President
>>> Developer Advocate @ Google Cloud Platform
>>>
>>> Blog: http://glaforge.appspot.com/
>>> Social: @glaforge / Google+
>>>
>>>
>>
>>
>>
>> --
>> Guillaume Laforge
>> Apache Groovy committer & PMC Vice-President
>> Developer Advocate @ Google Cloud Platform
>>
>> Blog: http://glaforge.appspot.com/
>> Social: @glaforge / Google+
>
>
>
> --
> Anthony Hepple
> 01704 227828 / 07931 504049
> http://www.dhdevelopment.co.uk