/** AWK~plus - Closure　& Annotation.
 */
val title1 = "Closure"
val title2 = "Nested closures"
val title3 = "Function value"
BEGIN {
    closure1
    closure2
    closure3
    print '.'
}
# @TypeChecked(TypeCheckingMode.SKIP)
function closure1() {
    val expect = 55
    var A = 0
    @CompileStatic
    #        printTitle() # 空の仮引数を省略できることを再発見しました.
    function printTitle { print "   ." title1 }  # 親のスコープを参照していないためルートに展開.
    @CompileStatic  # Groovy-Closureへの、Annotation付与は不可.
    function sum(n) {  # これは、Groovy-Closure.
        for (var i = 0; n >= ++i;)
            A += i
        return A
    }
    printTitle()
    val actual = sum(10)
    printf "\t<%d : %d>\n", expect, actual
    assertEquals(expect, actual, "#1")
}
# @TypeChecked(TypeCheckingMode.SKIP)
function closure2() {
    print "   ." title2
    var A = 0
    function sum(n) {  # これは、Groovy-Closure.
        var i = 0
        function increment() { ++i }  # これも、Closure.
        while (n >= increment())
            A += i
        return A
    }
    val expect = 55
    val actual = sum(10)
    printf "\t<%d : %d>\n", expect, actual
    assertEquals(expect, actual, "#2")
}
@CompileStatic  # 型推論をクラスファイルに反映(ダイナミック言語としての柔軟さは、失われる)
function closure3() {
    print "   ." title3
    function calc(x: Function) { return x.apply() }  # 関数を間数値として呼び出すためのコンテナ.
    function mod(a, b) { return a % b }  # 関数値(Function value)、必ずルートに展開すること.
    val expect = 3
    val actual = calc(.mod(7, 4)) # 関数値呼び出し.
    printf "\t<%d : %d>\n", expect, actual
    assertEquals(expect, actual, "#3")
}
# インライン関数が、親のスコープを参照している場合は、Groovy-Closureに展開されます。
# Groovy-Closureには、Annotationを付与出来ないことに注意してください。
# また、関数値(Function value)を使用する場合には、インライン関数をルートに移動させる必要があります。
# If the inline function refers to the scope of its parent,
# it will be expanded to Groovy-Closure.
# Please note that Annotation cannot be added to Groovy-Closure.
# Also, if you want to use a function value,
# you need to move the inline function to the root.