You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Yang Yang <re...@gmail.com> on 2017/01/20 07:22:20 UTC

A strange script

Script:
a = {x -> println x}
a("a${a}")

Output:
a
a

Why?

Re: A strange script

Posted by Anthony Hepple <an...@dhdevelopment.co.uk>.
I've got it. It's not just a StringWriter but the StringWriter that is
being used to build the GString, hence the 'magic' contents.

Many thanks Keith, Giullaume

Re: A strange script

Posted by Yang Yang <re...@gmail.com>.
Hi, all
Thank you for involving in this discussion. I get it too. x is s StringWriter and that make sense. I came up with this script when I'm learning Groovy and I replicate this kind of logic to the other scripting languages like JavaScript and so on. I want to figure out the internal handling mechanism of closure in string parameters, so I build this confusing script. 

Thanks again,
Guillaume, Keith and Anthony


> On 22 Jan 2017, at 03:47, Suderman Keith <su...@anc.org> wrote:
> 
> Oops, there is a last minute cut/paste error in my example script.  It should read:
> 
> a = { x -> 
> 	println x.class
> 	println x 
> 	x.write('foo')
> 	return 'bar' 
> }
> assert "no argument ${a}" == "no argument foo"
> 
> and it will print:
> 
> class java.io.StringWriter
> no argument 
> 
> Keith
> 
>> On Jan 21, 2017, at 2:37 PM, Suderman Keith <suderman@anc.org <ma...@anc.org>> wrote:
>> 
>> 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 <anthony@dhdevelopment.co.uk <ma...@dhdevelopment.co.uk>> 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 <glaforge@gmail.com <ma...@gmail.com>> 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 <reliveyy@gmail.com <ma...@gmail.com>> 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 <glaforge@gmail.com <ma...@gmail.com>> 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 <http://groovy-lang.org/syntax.html#_special_case_of_interpolating_closure_expressions>
>>>>> 
>>>>> Guillaume
>>>>> 
>>>>> 
>>>>> On Fri, Jan 20, 2017 at 8:22 AM, Yang Yang <re...@gmail.com> 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/ <http://glaforge.appspot.com/>
>>>> Social: @glaforge / Google+
>>> 
>>> 
>>> 
>>> -- 
>>> Anthony Hepple
>>> 01704 227828 / 07931 504049
>>> http://www.dhdevelopment.co.uk <http://www.dhdevelopment.co.uk/>
> 


Re: A strange script

Posted by Suderman Keith <su...@anc.org>.
Oops, there is a last minute cut/paste error in my example script.  It should read:

a = { x -> 
	println x.class
	println x 
	x.write('foo')
	return 'bar' 
}
assert "no argument ${a}" == "no argument foo"

and it will print:

class java.io.StringWriter
no argument 

Keith

> On Jan 21, 2017, at 2:37 PM, Suderman Keith <su...@anc.org> wrote:
> 
> 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 <an...@dhdevelopment.co.uk> 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 <gl...@gmail.com> 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 <re...@gmail.com> 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 <gl...@gmail.com> 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 <re...@gmail.com> 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


Re: A strange script

Posted by Suderman Keith <su...@anc.org>.
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 <an...@dhdevelopment.co.uk> 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 <gl...@gmail.com> 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 <re...@gmail.com> 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 <gl...@gmail.com> 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 <re...@gmail.com> 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


Re: A strange script

Posted by Anthony Hepple <an...@dhdevelopment.co.uk>.
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 <gl...@gmail.com> 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 <re...@gmail.com> 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 <gl...@gmail.com> 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 <re...@gmail.com> 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

Re: A strange script

Posted by Guillaume Laforge <gl...@gmail.com>.
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 <re...@gmail.com> 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 <gl...@gmail.com> 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 <re...@gmail.com> 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 <http://twitter.com/glaforge> / Google+
> <https://plus.google.com/u/0/114130972232398734985/posts>
>
>
>


-- 
Guillaume Laforge
Apache Groovy committer & PMC Vice-President
Developer Advocate @ Google Cloud Platform

Blog: http://glaforge.appspot.com/
Social: @glaforge <http://twitter.com/glaforge> / Google+
<https://plus.google.com/u/0/114130972232398734985/posts>

Re: A strange script

Posted by Yang Yang <re...@gmail.com>.
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 <gl...@gmail.com> 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 <http://groovy-lang.org/syntax.html#_special_case_of_interpolating_closure_expressions>
> 
> Guillaume
> 
> 
> On Fri, Jan 20, 2017 at 8:22 AM, Yang Yang <reliveyy@gmail.com <ma...@gmail.com>> 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/ <http://glaforge.appspot.com/>
> Social: @glaforge <http://twitter.com/glaforge> / Google+ <https://plus.google.com/u/0/114130972232398734985/posts>

Re: A strange script

Posted by Guillaume Laforge <gl...@gmail.com>.
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 <re...@gmail.com> 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 <http://twitter.com/glaforge> / Google+
<https://plus.google.com/u/0/114130972232398734985/posts>