I think a GEP would be the right thing for a change like this. I'd be
willing to help try to put it together.
I'd hope we could come up with an approach which allows eager or lazy.
I don't want to get hung up on syntax but perhaps "${x}" could be eager and
"${ -> x }"
could be the current semantics or some alternative to this.But anyway, a GEP could outline the exact proposed change across dynamic and static Groovy with pros and cons etc. Cheers, Paul. On Sat, Sep 8, 2018 at 11:07 AM Daniel.Sun <[email protected]> wrote: > Hi all, > > In most of cases, we just use GString as an enhanced String, but > currently GString is not implemented eager so it has some weird features, > which will confuse users. Let's look at some examples[1] from Jochen: > > * the referenced variables are bound eager > * toString on GString evaluates the GString, this includes toString for the > values > ``` > def x = 1 > def gstring = "$x" > assert gstring == "1" > x = 2 > assert gstring == "1" > ``` > ``` > class X { > int i = 0 > String toString(){Integer.toString(i++)} > } > def x = new X() > def gstring = "$x" > assert gstring == "0" > assert gstring == "1" // the content of gstring changed... > ``` > > If we implement GString eager and treated as normal String(not expose > GString API), the content of GString will not change once it is evaluated. > We can get the following benefits: > 1) Users will not be confused because of some weird feature; > 2) Better compatibility between dynamic and static compilation, SEE > GROOVY-6668[1]; > 3) The performance will be improved to some extent because GString will > not > be evaluated again and again even if its content is not changed; > > The proposal is a breaking change, so I propose it is targeted to > groovy 3.0.0 if accepted. > > P.S. some issues like GROOVY-6668 are raised by users again and again, that > is say, many users are confused by current implementation, i.e. GString can > not be treated as normal String in STC. In the static compilation mode: > ``` > @groovy.transform.CompileStatic > class Test { > static void main(String[] args) { > def m = ['a':1, 'b':2] > def k = 'a' > assert 1 == m[k] > assert 1 == m["$k" as String] > assert 1 == m["$k"] // fails, gets null, which is not equal to 1 > } > } > > ``` > > > Cheers, > Daniel.Sun > > [1] https://github.com/apache/groovy/pull/708 > > > > > > ----- > Daniel Sun > Apache Groovy committer > Blog: http://blog.sunlan.me > Twitter: @daniel_sun > > -- > Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html >
