Поиск…


Синтаксис

  • @goto label
  • метка @label

замечания

Чрезмерное использование или неправильное использование расширенного потока управления делает код трудным для чтения. @goto или его эквиваленты на других языках при неправильном использовании приводит к нечитаемому коду спагетти.

Подобно языкам типа C, нельзя переключаться между функциями в Julia. Это также означает, что @goto невозможно на верхнем уровне; он будет работать только внутри функции. Кроме того, нельзя переходить от внутренней функции к ее внешней функции или от внешней функции к внутренней функции.

Проверка ввода

Хотя это не традиционно считается циклом, макросы @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

Хотя оба примера делают то же самое, второе легче понять. Однако первый из них более эффективен (поскольку он позволяет избежать рекурсивного вызова). В большинстве случаев стоимость звонка не имеет значения; но в ограниченных ситуациях первая форма приемлема.

Очистка ошибок

В таких языках, как C, оператор @goto часто используется, чтобы гарантировать, что функция очищает необходимые ресурсы, даже в случае ошибки. Это менее важно в Julia, потому что вместо этого часто используются блоки исключений и try finally .

Однако код Julia может взаимодействовать с C-кодом и API-интерфейсом C, поэтому иногда функции должны быть написаны как C-код. Приведенный ниже пример надуман, но демонстрирует общий прецедент. Код Julia вызовет Libc.malloc для выделения некоторой памяти (это имитирует вызов API C). Если не все распределения успешны, то функция должна освобождать ресурсы, полученные до сих пор; в противном случае возвращается выделенная память.

using Base.Libc
function allocate_some_memory()
    mem1 = malloc(100)
    mem1 == C_NULL && @goto fail
    mem2 = malloc(200)
    mem2 == C_NULL && @goto fail
    mem3 = malloc(300)
    mem3 == C_NULL && @goto fail
    return mem1, mem2, mem3

@label fail
    free(mem1)
    free(mem2)
    free(mem3)
end


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow