[ 
https://issues.apache.org/jira/browse/GROOVY-8301?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16424692#comment-16424692
 ] 

mgroovy commented on GROOVY-8301:
---------------------------------

Could the inlining be done much earlier ? I conceptually always see this more 
from a "macro perspective":
 # wrap the to be inserted code block in a surrounding "setup/teardown" block
 # and replace parameters and variables by uniquely named equivalents

Schematic sample:
{code:java}
@Inline
def myInlineMacro(p0,p1,...,pn, Block block) {
        openInlineBracket(p0,p1,...,pn) 
        block.inline(p0,p1,...,pn) 
        closeInlineBracket(p0,p1,...,pn)
}
{code}
Concrete example:
{code:java}
// Inside Sql-like Groovy class
@Inline
void eachRowInline(GString sql, int maxRows, Block block) { // block replaces 
closure argument
        final ConnectionStatementResultSet csr = createCsr() // Create 
resources (connection, statement, resultSet)
        try {
                GroovyResultSet groovyRS = groovyResultSet(sql, csr)
                int i = 0
                while((maxRows <= 0 || i++ < maxRows) && groovyRS.next()) {
                        block.inline(groovyRS) // Passed block will be inlined 
here (together with surrounding code) 
                }
        } 
        finally { cleanUp(csr) } // clean up resources
}
{code}
Usage:
{code:java}
db.eachRowInline("select * from PERSON", mxRws) { final row ->
        println row
}
{code}
should become (in place):
{code:java}
final GString sql$0 = "select * from PERSON" // Parameters & variables become 
uniquely named local variables
final GString maxRows$0 = mxRws
final ConnectionStatementResultSet csr$0 = db.createCsr()
try {
        GroovyResultSet groovyRS$0 = groovyResultSet(sql$0, csr$0)
        int i$0 = 0
        while((maxRows$0 <= 0 || i$0++ < maxRows$0) && groovyRS$0.next()) {
                println groovyRS$0 // row -> groovyRS$0
        }
} 
finally { cleanUp(csr$0) } 
{code}

> break/return/continue support in "Appended Block Closures"
> ----------------------------------------------------------
>
>                 Key: GROOVY-8301
>                 URL: https://issues.apache.org/jira/browse/GROOVY-8301
>             Project: Groovy
>          Issue Type: New Feature
>          Components: Compiler
>            Reporter: mgroovy
>            Priority: Major
>              Labels: break, closure, continue, inline, return
>
> This proposal revisits the idea to change the semantics of the break, return, 
> and continue keyword for closures that are used in a way that mimics Java 
> block constructs such as if, for, or while.
> Example 1:
> {code}
> // Iterate over all PERSON rows in the result set
> sqe.forEachRow("select * from PERSON") { final row ->
>   if(row.TAG == 0) { break } // Leave forEachRow loop
>   if(row.TAG == 1) { return } // return from the method enclosing the 
> forEachRow loop
>   if(row.TAG == 2) { continue } // Move to next iteration in the forEachRow 
> loop
> }
> {code}
> Example 2:
> {code}
> // Encapsulate with statically imported helper method that catches exceptions 
> and ignores them, if the passed parameter is true
> execWithOptionalIgnoreErrors(ignoreErrorsQ) {
>   final x = dangerousOperation() 
>   if(x == 1) { return } // return from the enclosing method
>   // Note: break & continue are not allowed here
> }
> {code}
> Support for continue can trivially be mapped to a return statement inside the 
> closure, so what one needs to look at is how to support leaving the iteration 
> ("break" semantics) and returning from the enclosing method ("return" 
> semantics). With current Groovy closures there are two known potential 
> approaches to achieve this behavior:
> # Use try-catch to simulate a non-local goto to "jump" to the right spot.
> ** Described e.g. here 
> http://blackdragsview.blogspot.co.at/2006/09/non-local-transfers-in-groovy-90.html
>  by [~blackdrag].
> ** Drawbacks of the approach:
> ### If the user wraps a try-catch-everything (i.e. catching Exception or 
> Throwable base class) around the code, the mechanism will break in an 
> unexpected way.
> ### Exceptions incur a certain performance overhead.
> # Use special return values that indicate whether to break or return.
> ** This evidently works for all cases which have no return value (e.g. 
> forEach)
> ** For all other cases one could make the closure return an Object, which 
> would again allow to discern regular return values from 
> break/return-semantics return values, if specific classes (e.g. 
> GroovyClosureBreak) are returned
> *** Since casting is required in this case, as small overhead is again 
> incurred
> ** A big drawback is that for both cases for "return" semantics all 
> surrounding methods would need to have / made to have Object as return type.
> ** This approach could be used to supply "continue" and "break" semantics 
> only.
> *** Note that having more than one return in a method is also often 
> considered bad style, so one could argue that "continue" and "break" 
> semantics are the more important of the three to support.
> A different approach would be to introduce "inline closures" to Groovy. These 
> closures would effectively be treated as inline block constructs, the same as 
> they already exist for e.g. regular for loops. This feature would make 
> contine/break/return support for "closures" trivial, since the keywords would 
> just automatically work as expected if the closure code is inlined.
> * This approach is used e.g. by the Kotlin programming language 
> https://kotlinlang.org/docs/reference/inline-functions.html
> * Kotlin uses a seperate "inline" keyword for this. I feel like supplying an 
> annotatio in Groovy to indicate inlining would be the more Groovy/flexible 
> (can be combined with other annotations) approach (Kotlin to me generally 
> seems to suffer from an overabundance of keywords)
> * Allowing inlining is also a feature that could also be applied for general 
> methods.
> * Leaving implementation effort aside, this approach to me looks like the 
> best way forward, it
> ## never breaks
> ## never incurs any performance overhead
> ## is elegant
> ## potentially can be used for applications that go beyond the topic of this 
> issue
> * Note: The general version of this feature has already been suggested in 
> GROOVY-6880 with regards to performance improvements. I agree that potential 
> performance improvements are not a strong enough argument to introduce this, 
> automatic break/contine/return support for inlined closures to me is.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to