Szukaj…


Składnia

  • @goto label
  • Etykieta @label

Uwagi

Nadużywanie lub niewłaściwe stosowanie zaawansowanego przepływu sterowania utrudnia odczyt kodu. @goto lub jego odpowiedniki w innych językach, jeśli są niewłaściwie używane, prowadzą do nieczytelnego kodu spaghetti.

Podobnie jak języki takie jak C, nie można przeskakiwać między funkcjami w Julii. Oznacza to również, że @goto nie jest możliwe na najwyższym poziomie; będzie działać tylko w ramach funkcji. Ponadto nie można przeskoczyć z funkcji wewnętrznej do jej funkcji zewnętrznej lub z funkcji zewnętrznej do funkcji wewnętrznej.

Sprawdzanie poprawności danych wejściowych

Chociaż nie są tradycyjnie uważane za pętle, makra @goto i @label mogą być używane do bardziej zaawansowanego przepływu sterowania. Jednym z przypadków użycia jest awaria jednej części, która powinna doprowadzić do ponownej próby całej funkcji, często przydatnej w sprawdzaniu poprawności danych wejściowych:

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

Jednak ten przypadek użycia jest często bardziej przejrzysty przy użyciu rekurencji:

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

Chociaż oba przykłady robią to samo, drugi jest łatwiejszy do zrozumienia. Jednak pierwszy z nich jest bardziej wydajny (ponieważ pozwala uniknąć połączenia rekurencyjnego). W większości przypadków koszt połączenia nie ma znaczenia; ale w ograniczonych sytuacjach pierwsza forma jest dopuszczalna.

Błąd czyszczenia

W językach takich jak C często używana jest instrukcja @goto aby zapewnić, że funkcja wyczyści niezbędne zasoby, nawet w przypadku błędu. Jest to mniej ważne w Julii, ponieważ wyjątki i try - w finally często używane są bloki.

Możliwe jest jednak, że kod Julii będzie się łączył z kodem C i interfejsami API C, więc czasami funkcje muszą być napisane tak jak kod C. Poniższy przykład został opracowany, ale pokazuje typowy przypadek użycia. Kod Julia wywoła Libc.malloc aby przydzielić trochę pamięci (symuluje to wywołanie C API). Jeśli nie wszystkie alokacje się powiodą, funkcja powinna uwolnić dotychczasowe zasoby; w przeciwnym razie przydzielona pamięć zostanie zwrócona.

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow