Julia Language
@goto e @label
Ricerca…
Sintassi
- Etichetta @goto
- etichetta @label
Osservazioni
L'uso eccessivo o inappropriato del flusso di controllo avanzato rende il codice difficile da leggere. @goto
o i suoi equivalenti in altre lingue, se usati in modo improprio, portano a codice spaghetti illeggibile.
Simile alle lingue come C, non si può saltare tra le funzioni di Julia. Ciò significa anche che @goto
non è possibile al livello più alto; Funzionerà solo all'interno di una funzione. Inoltre, non si può saltare da una funzione interiore alla sua funzione esterna, o da una funzione esterna a una funzione interiore.
Convalida dell'input
Sebbene non siano tradizionalmente considerati loop, i macro @goto
e @label
possono essere utilizzati per un flusso di controllo più avanzato. Un caso d'uso è quando il fallimento di una parte dovrebbe portare al nuovo tentativo di un'intera funzione, spesso utile nella convalida dell'input:
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
Tuttavia, questo caso d'uso è spesso più chiaro usando la ricorsione:
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
Sebbene entrambi gli esempi facciano la stessa cosa, il secondo è più facile da capire. Tuttavia, il primo è più performante (perché evita la chiamata ricorsiva). Nella maggior parte dei casi, il costo della chiamata non ha importanza; ma in situazioni limitate, la prima forma è accettabile.
Pulizia errore
In linguaggi come C, l'istruzione @goto
viene spesso utilizzata per garantire che una funzione pulisca le risorse necessarie, anche in caso di errore. Questo è meno importante in Julia, perché le eccezioni e i blocchi try
- finally
vengono spesso utilizzati.
Tuttavia, è possibile che il codice Julia si interfaccia con il codice C e le API C, quindi a volte le funzioni devono ancora essere scritte come il codice C. L'esempio seguente è ideato, ma dimostra un caso d'uso comune. Il codice Julia chiamerà Libc.malloc
per allocare memoria (simula una chiamata API C). Se non tutte le allocazioni sono riuscite, allora la funzione dovrebbe liberare le risorse ottenute finora; in caso contrario, viene restituita la memoria allocata.
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