You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by Nathan Harvey <na...@gmail.com> on 2017/12/21 22:20:44 UTC

G-String embedded Closure calling bug?

Take the following code:

int triggered = 0
def o = { -> triggered++ }
		
println(o) // A
println("$o") // B
println("${o}") // C

After A, triggered is 0; after B, it's 1; after C, it's 2. The Closure is
being called and the result of it is being printed instead. Is this behavior
intended?



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: G-String embedded Closure calling bug?

Posted by Jochen Theodorou <bl...@gmx.org>.
On 22.12.2017 16:55, Daniel.Sun wrote:
> Hi Jochen,
> 
>        As far as I remember,  John Wilson is one of main contributors of
> Groovy, he is active in about 2007 and rejected some proposals of mine ;-)

he did a lot of work for Groovy 1.0 for example and way before too (with 
a gap of quite some time) yes. Which is why it was difficult to argue 
against those things back then. Guillaume will remember some of the 
heated discussions.

And I am not saying what he did is wrong or stupid. Nothing like that, 
no. But the usage of the language changes and we did tend to overload 
constructs a bit too much in the past

bye Jochen

Re: G-String embedded Closure calling bug?

Posted by "Daniel.Sun" <su...@apache.org>.
Hi Jochen,

      As far as I remember,  John Wilson is one of main contributors of
Groovy, he is active in about 2007 and rejected some proposals of mine ;-)

Cheers,
Daniel.Sun



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: G-String embedded Closure calling bug?

Posted by Jochen Theodorou <bl...@gmx.org>.
On 22.12.2017 00:20, Paul King wrote:
> I suspect this is intentional but was before my time. Try this also:
> 
> int triggered = 0
> def o1 = { -> triggered++ }
> def o2 = { println '*' + it; triggered++ }
> 
> println(o1) // ConsoleScript11$_run_closure1@xxxxxxxx
> println(o2) // ConsoleScript11$_run_closure2@yyyyyyyy
> 
> assert triggered == 0
> println("xyzzy$o1") // xyzzy0
> assert triggered == 1
> println("XX${o2}YY${o2(42)}ZZ") // *42\n*XX\nXXYY1ZZ
> assert triggered == 3

ah yes... good old times with John Wilson... I think the idea was back 
then to leverage the Closures for templating engine purposes.. like for 
example GStringTemplateEngine the whole template in there is basically a 
Closure and writing is channeld by the writeTo method, that is also used 
for toString.

I really wonder how much this feature is used. If you look at the code 
you will see, that it does lead to very surprising behaviour, for 
example toString on Closure and writeTo in GString do not fit very well 
together and the GString base evaluation may lead to a double evaluation 
by working on the result of the Closure call. Plus of course the 
different behaviour for if the closure does or does not take a parameter 
where we one time work on the result and one time we ignore the result 
and instead let the Closure itself work things out.

Frankly, this is on my list of features to be removed. I have not yet 
fully investigated the impact of this - and I suspect there will be much 
more impact here than it looks like on first glance

bye Jochen



Re: G-String embedded Closure calling bug?

Posted by Nathan Harvey <na...@gmail.com>.
Yeah, I don't understand this behavior either. Seems better to write "${o()}"
if you want call it. Anyone against changing that?

MG, yes that operator has been proposed for Parrot, but I'm not sure what
happened to it. Maybe start another thread for it.



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: G-String embedded Closure calling bug?

Posted by mg <mg...@arscreat.com>.
I have never wanted to embed a Closure obj in a GString, but the behavior is definitely a bit unexpected.
I must admit that I feel that Groovy features like being able to iterate over null, or that an empty collection is Groovy-true are more of a problem imho. I have never had any application for the latter, but have a lot of code where I have to say
final cols = colsIn != null ? colsIn : defaultCols()
instead of just
final cols = colsIn ?: defaultCols()

Btw has an ?= operator ever been suggested, which assigns the RHS iff the LHS has value null ? If it where also supported for assigning default parameter values one could do:
void foo(final Columns cols ?= defaultCols(), String s) {  s ?= defaultString()}
This would allow to pass in null as parameter value which is passed through several calls without the need to duplicate e.g. the cols parameter default value in method definitions, and elegantly assign the default value in the last method called...


-------- Ursprüngliche Nachricht --------Von: Paul King <pa...@asert.com.au> Datum: 22.12.17  00:25  (GMT+01:00) An: dev@groovy.apache.org Betreff: Re: G-String embedded Closure calling bug? 
Or change the last two lines a little more:

println("XX${o2}YY${o2(42)}ZZ$o2")  // *42\n*XX\n*XXYY1ZZ\nXXYY1ZZassert triggered == 4
It looks weird to me but perhaps there was a reason to it?

On Fri, Dec 22, 2017 at 9:20 AM, Paul King <pa...@asert.com.au> wrote:
I suspect this is intentional but was before my time. Try this also:

int triggered = 0def o1 = { -> triggered++ }def o2 = { println '*' + it; triggered++ }
println(o1) // ConsoleScript11$_run_closure1@xxxxxxxxprintln(o2) // ConsoleScript11$_run_closure2@yyyyyyyy
assert triggered == 0println("xyzzy$o1") // xyzzy0assert triggered == 1println("XX${o2}YY${o2(42)}ZZ") // *42\n*XX\nXXYY1ZZassert triggered == 3

On Fri, Dec 22, 2017 at 8:20 AM, Nathan Harvey <na...@gmail.com> wrote:
Take the following code:



int triggered = 0

def o = { -> triggered++ }



println(o) // A

println("$o") // B

println("${o}") // C



After A, triggered is 0; after B, it's 1; after C, it's 2. The Closure is

being called and the result of it is being printed instead. Is this behavior

intended?







--

Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html






Re: G-String embedded Closure calling bug?

Posted by Paul King <pa...@asert.com.au>.
Or change the last two lines a little more:

println("XX${o2}YY${o2(42)}ZZ$o2")  // *42\n*XX\n*XXYY1ZZ\nXXYY1ZZ
assert triggered == 4

It looks weird to me but perhaps there was a reason to it?


On Fri, Dec 22, 2017 at 9:20 AM, Paul King <pa...@asert.com.au> wrote:

> I suspect this is intentional but was before my time. Try this also:
>
> int triggered = 0
> def o1 = { -> triggered++ }
> def o2 = { println '*' + it; triggered++ }
>
> println(o1) // ConsoleScript11$_run_closure1@xxxxxxxx
> println(o2) // ConsoleScript11$_run_closure2@yyyyyyyy
>
> assert triggered == 0
> println("xyzzy$o1") // xyzzy0
> assert triggered == 1
> println("XX${o2}YY${o2(42)}ZZ") // *42\n*XX\nXXYY1ZZ
> assert triggered == 3
>
>
> On Fri, Dec 22, 2017 at 8:20 AM, Nathan Harvey <na...@gmail.com>
> wrote:
>
>> Take the following code:
>>
>> int triggered = 0
>> def o = { -> triggered++ }
>>
>> println(o) // A
>> println("$o") // B
>> println("${o}") // C
>>
>> After A, triggered is 0; after B, it's 1; after C, it's 2. The Closure is
>> being called and the result of it is being printed instead. Is this
>> behavior
>> intended?
>>
>>
>>
>> --
>> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>>
>
>

Re: G-String embedded Closure calling bug?

Posted by Paul King <pa...@asert.com.au>.
I suspect this is intentional but was before my time. Try this also:

int triggered = 0
def o1 = { -> triggered++ }
def o2 = { println '*' + it; triggered++ }

println(o1) // ConsoleScript11$_run_closure1@xxxxxxxx
println(o2) // ConsoleScript11$_run_closure2@yyyyyyyy

assert triggered == 0
println("xyzzy$o1") // xyzzy0
assert triggered == 1
println("XX${o2}YY${o2(42)}ZZ") // *42\n*XX\nXXYY1ZZ
assert triggered == 3


On Fri, Dec 22, 2017 at 8:20 AM, Nathan Harvey <na...@gmail.com>
wrote:

> Take the following code:
>
> int triggered = 0
> def o = { -> triggered++ }
>
> println(o) // A
> println("$o") // B
> println("${o}") // C
>
> After A, triggered is 0; after B, it's 1; after C, it's 2. The Closure is
> being called and the result of it is being printed instead. Is this
> behavior
> intended?
>
>
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>

Re: G-String embedded Closure calling bug?

Posted by MG <mg...@arscreat.com>.
I know where you are coming from. On the other hand, this is maybe the 
sole reason why anyone would need a language after Groovy: Historic 
features being frozen because of the fear that a change might break some 
existing code...

However I do not think that this behavior, as unexpected as it might be, 
falls into that category, given that my code makes heavy use of 
embedding expressions in GString|s and I have never run into it. The 
only place where this might be a problem, is, if you actually want to 
debug output some information about a Closure object, and you instead 
get an (unexpected) Closure evaluation.

I would therefore suggest another solution for this: In my code I have a 
ToDebugString interface, which requires a class implements a
String toDebugString()
method, which is expected to return human readable debug information 
about the object.
I think would be a generally useful concept, by allowing the programmer 
to distinguish between debug- and other toString-semantics if need be.

I propose Groovy introduces toDebugString as a core concept, with 
default implementation calling the Java default Object#toString method.
(Or returns something along the line of getClass().simpleName + '@' + 
System.identityHashcode(this);  falling back to the class' toString 
method would also be an option, although in most cases it's most likely 
not what the user wants/expects.)

As an extension (and the way I use it), toDebugString could look like this:
String toDebugString(int indentationLevel = 0, String indentationString 
= '\t')
and implementations are expected to indent the resulting String 
accordingly, which is very helpful for complex objects which require a 
multi-line output to make sense of them in a debug log.

What do you guys think ?
mg


On 31.12.2017 11:58, Guillaume Laforge wrote:
> We've settled on that behavior a long time ago, so it's quite blurry 
> in my mind, to be honest.
> I'd be a bit afraid of making changes to how things are working now, 
> as it might have some unintended consequences.
> I mean, making some changes there could break people's code in 
> unexpected places, and I think it would be pretty hard to track and find.
> With age (not that I'm old, but I've been involved in Groovy for 14 
> years now), I become a bit more conservative, and afraid of making 
> anything that could be breaking people's code :-(
>
> Guillaume
>
>
> On Sun, Dec 31, 2017 at 4:57 AM, Nathan Harvey 
> <nathanwharvey@gmail.com <ma...@gmail.com>> wrote:
>
>     Are there any more thoughts on whether or not this behavior should be
>     changed? I say it is confusing and unnecessary.  I think it's
>     important to
>     keep the behavior advertised for Closures intact, eg: "hello {->
>     0}" should
>     still render 0, but a reference to a Closure should not
>     automatically call
>     toString()
>
>
>
>     --
>     Sent from:
>     http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>     <http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html>
>
>
>
>
> -- 
> 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: G-String embedded Closure calling bug?

Posted by Guillaume Laforge <gl...@gmail.com>.
We've settled on that behavior a long time ago, so it's quite blurry in my
mind, to be honest.
I'd be a bit afraid of making changes to how things are working now, as it
might have some unintended consequences.
I mean, making some changes there could break people's code in unexpected
places, and I think it would be pretty hard to track and find.
With age (not that I'm old, but I've been involved in Groovy for 14 years
now), I become a bit more conservative, and afraid of making anything that
could be breaking people's code :-(

Guillaume


On Sun, Dec 31, 2017 at 4:57 AM, Nathan Harvey <na...@gmail.com>
wrote:

> Are there any more thoughts on whether or not this behavior should be
> changed? I say it is confusing and unnecessary.  I think it's important to
> keep the behavior advertised for Closures intact, eg: "hello {-> 0}" should
> still render 0, but a reference to a Closure should not automatically call
> toString()
>
>
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>



-- 
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: G-String embedded Closure calling bug?

Posted by Nathan Harvey <na...@gmail.com>.
Are there any more thoughts on whether or not this behavior should be
changed? I say it is confusing and unnecessary.  I think it's important to
keep the behavior advertised for Closures intact, eg: "hello {-> 0}" should
still render 0, but a reference to a Closure should not automatically call
toString()



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html