[
https://issues.apache.org/jira/browse/GROOVY-8301?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16408877#comment-16408877
]
Paul King commented on GROOVY-8301:
-----------------------------------
There is a back-door mechanism for doing break that was originally baked into
Closures (you can set a directive to DONE or SKIP) but SKIP isn't implemented
at all and DONE is rarely supported widely. It has to be hard-coded into each
DGM method. There are a few that support it:
{code}
100.times {
if (it == 4) directive = Closure.DONE
println it
}
def collector = []
(1..100).collect(collector){ if (it == 4) directive = Closure.DONE; it ** 2 }
println collector
{code}
We haven't advertised this mechanism because we wondered whether we should
delete it since it is hardly supported. And that may still be the best thing to
do - but I mention it here while ideas are being discussed.
> 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)