// closures.groovy — closures: blocks of code you can store, pass and call. // A closure literal: { parameters -> body } def greet = { String name -> "Hello, $name!" } println greet('Acme') // call like a method println greet.call('Globex') // or with call() // One parameter? Use the implicit 'it' def shout = { it.toUpperCase() + '!' } println shout('boomi') // No parameters def now = { -> 'it is time' } println now() // Multiple parameters and default values def lineTotal = { qty, price, discount = 0 -> qty * price * (1 - discount / 100) } println lineTotal(10, 20) // 200 println lineTotal(10, 20, 15) // 170.00 // Closures as arguments: the last closure can go outside the parentheses def retry(int times, Closure action) { for (attempt in 1..times) { try { return action(attempt) } catch (e) { println " attempt $attempt failed: ${e.message}" } } 'gave up' } def result = retry(3) { attempt -> if (attempt < 3) throw new RuntimeException('timeout') "succeeded on attempt $attempt" } println result // Closures capture variables from where they were defined — and CAN change them def total = 0 [250, 90, 1200].each { amount -> total += amount } println "Total: $total" // 1540 // Returning closures: a function factory def multiplier = { factor -> { number -> number * factor } } def triple = multiplier(3) println triple(7) // 21 // Method pointer: turn a method into a closure with .& def upper = 'x'.&toUpperCase // bound to the string 'x' println upper() // X def isEven = { it % 2 == 0 } println([1, 2, 3, 4].findAll(isEven)) // [2, 4]