输入验证

虽然传统上不考虑循环,但 @goto@label 宏可用于更高级的控制流程。一个用例是当一个部分的失败导致整个函数的重试时,通常在输入验证中有用:

function getsequence()
    local a, b

@label start
    print("Input an integer: ")
    try
        a = parse(Int, readline())
    catch
        println("Sorry, that's not an integer.")
        @goto start
    end

    print("Input a decimal: ")
    try
        b = parse(Float64, readline())
    catch
        println("Sorry, that doesn't look numeric.")
        @goto start
    end

    a, b
end

但是,使用递归通常更清楚这个用例:

function getsequence()
    local a, b

    print("Input an integer: ")
    try
        a = parse(Int, readline())
    catch
        println("Sorry, that's not an integer.")
        return getsequence()
    end

    print("Input a decimal: ")
    try
        b = parse(Float64, readline())
    catch
        println("Sorry, that doesn't look numeric.")
        return getsequence()
    end

    a, b
end

虽然两个例子都做同样的事情,但第二个更容易理解。但是,第一个更高性能(因为它避免了递归调用)。在大多数情况下,通话费用无关紧要; 但在有限的情况下,第一种形式是可以接受的。