Best pattern for simulating “continue” in Groovy closure

前端 未结 6 1953
难免孤独
难免孤独 2020-12-08 01:54

It seems that Groovy does not support break and continue from within a closure. What is the best way to simulate this?

revs.eachLin         


        
6条回答
  •  旧巷少年郎
    2020-12-08 02:23

    Closures cannot break or continue because they are not loop/iteration constructs. Instead they are tools used to process/interpret/handle iterative logic. You can ignore given iterations by simply returning from the closure without processing as in:

    revs.eachLine { line -> 
        if (line ==~ /-{28}/) {
                return
        }
    
    }
    

    Break support does not happen at the closure level but instead is implied by the semantics of the method call accepted the closure. In short that means instead of calling "each" on something like a collection which is intended to process the entire collection you should call find which will process until a certain condition is met. Most (all?) times you feel the need to break from a closure what you really want to do is find a specific condition during your iteration which makes the find method match not only your logical needs but also your intention. Sadly some of the API lack support for a find method... File for example. It's possible that all the time spent arguing wether the language should include break/continue could have been well spent adding the find method to these neglected areas. Something like firstDirMatching(Closure c) or findLineMatching(Closure c) would go a long way and answer 99+% of the "why can't I break from...?" questions that pop up in the mailing lists. That said, it is trivial to add these methods yourself via MetaClass or Categories.

    class FileSupport {
       public static String findLineMatching(File f, Closure c) {
          f.withInputStream {
             def r = new BufferedReader(new InputStreamReader(it))
             for(def l = r.readLine(); null!=l; l = r.readLine())
                 if(c.call(l)) return l
             return null
          }
       }
    }
    
    using(FileSupport) { new File("/home/me/some.txt").findLineMatching { line ==~ /-{28}/ }
    

    Other hacks involving exceptions and other magic may work but introduce extra overhead in some situations and convolute the readability in others. The true answer is to look at your code and ask if you are truly iterating or searching instead.

提交回复
热议问题