Julia Language
tandis que les boucles
Recherche…
Syntaxe
- tandis que cond; corps; fin
- Pause
- continuer
Remarques
Le while
en boucle ne possède pas de valeur; Bien qu'il puisse être utilisé dans une position d'expression, son type est Void
et la valeur obtenue ne sera nothing
.
Séquence Collatz
Le while
en boucle court son corps aussi longtemps que la condition est. Par exemple, le code suivant calcule et imprime la séquence Collatz à partir d'un nombre donné:
function collatz(n)
while n ≠ 1
println(n)
n = iseven(n) ? n ÷ 2 : 3n + 1
end
println("1... and 4, 2, 1, 4, 2, 1 and so on")
end
Usage:
julia> collatz(10)
10
5
16
8
4
2
1... and 4, 2, 1, 4, 2, 1 and so on
Il est possible d'écrire une boucle récursive, et complexe while
boucles, parfois la variante récursive est plus claire. Cependant, chez Julia, les boucles présentent des avantages distincts par rapport à la récursivité:
- Julia ne garantit pas l'élimination des appels de queue, la récursivité utilise donc de la mémoire supplémentaire et peut provoquer des erreurs de dépassement de capacité de la pile.
- De plus, pour la même raison, une boucle peut avoir un temps de traitement réduit et s'exécuter plus rapidement.
Exécuter une fois avant de tester la condition
Parfois, on veut exécuter du code d'initialisation une fois avant de tester une condition. Dans certaines autres langues, ce genre de boucle a spécial do
- while
la syntaxe. Cependant, cette syntaxe peut être remplacée par une instruction while
boucle et break
, de sorte que Julia n'a pas de syntaxe do
- while
spécialisée. Au lieu de cela, on écrit:
local name
# continue asking for input until satisfied
while true
# read user input
println("Type your name, without lowercase letters:")
name = readline()
# if there are no lowercase letters, we have our result!
!any(islower, name) && break
end
Notez que dans certaines situations, de telles boucles pourraient être plus claires avec la récursivité:
function getname()
println("Type your name, without lowercase letters:")
name = readline()
if any(islower, name)
getname() # this name is unacceptable; try again
else
name # this name is good, return it
end
end
Recherche en largeur
(Bien que cet exemple soit écrit en utilisant la syntaxe introduite dans la version v0.5, il peut également fonctionner avec peu de modifications sur les anciennes versions.)
Cette implémentation de la recherche en largeur (BFS) sur un graphique représenté avec des listes de contiguïté utilise les boucles while
et la déclaration de return
. La tâche que nous allons résoudre est la suivante: nous avons une séquence de personnes et une séquence d’amitiés (les amitiés sont mutuelles). Nous voulons déterminer le degré de connexion entre deux personnes. Autrement dit, si deux personnes sont amis, nous reviendrons à 1
; si l'un est un ami d'un ami de l'autre, nous reviendrons à 2
, et ainsi de suite.
Tout d'abord, supposons que nous ayons déjà une liste d'adjacence: un Dict
mapping T
to Array{T, 1}
, où les clés sont des personnes et les valeurs sont toutes les amies de cette personne. Ici, nous pouvons représenter des personnes avec le type T
choisi. dans cet exemple, nous utiliserons Symbol
. Dans l'algorithme BFS, nous conservons une file d'attente de personnes pour «visiter» et marquer leur distance par rapport au nœud d'origine.
function degree(adjlist, source, dest)
distances = Dict(source => 0)
queue = [source]
# until the queue is empty, get elements and inspect their neighbours
while !isempty(queue)
# shift the first element off the queue
current = shift!(queue)
# base case: if this is the destination, just return the distance
if current == dest
return distances[dest]
end
# go through all the neighbours
for neighbour in adjlist[current]
# if their distance is not already known...
if !haskey(distances, neighbour)
# then set the distance
distances[neighbour] = distances[current] + 1
# and put into queue for later inspection
push!(queue, neighbour)
end
end
end
# we could not find a valid path
error("$source and $dest are not connected.")
end
Maintenant, nous allons écrire une fonction pour construire une liste d'adjacence à partir d'une séquence de personnes, et une séquence de tuples (person, person)
:
function makeadjlist(people, friendships)
# dictionary comprehension (with generator expression)
result = Dict(p => eltype(people)[] for p in people)
# deconstructing for; friendship is mutual
for (a, b) in friendships
push!(result[a], b)
push!(result[b], a)
end
result
end
Nous pouvons maintenant définir la fonction d'origine:
degree(people, friendships, source, dest) =
degree(makeadjlist(people, friendships), source, dest)
Maintenant, testons notre fonction sur certaines données.
const people = [:jean, :javert, :cosette, :gavroche, :éponine, :marius]
const friendships = [
(:jean, :cosette),
(:jean, :marius),
(:cosette, :éponine),
(:cosette, :marius),
(:gavroche, :éponine)
]
Jean est connecté en 0
étapes:
julia> degree(people, friendships, :jean, :jean)
0
Jean et Cosette sont amis et ont donc un diplôme 1
:
julia> degree(people, friendships, :jean, :cosette)
1
Jean et Gavroche sont connectés indirectement via Cosette puis Marius, leur diplôme est donc 3
:
julia> degree(people, friendships, :jean, :gavroche)
3
Javert et Marius ne sont connectés via aucune chaîne, une erreur est donc générée:
julia> degree(people, friendships, :javert, :marius)
ERROR: javert and marius are not connected.
in degree(::Dict{Symbol,Array{Symbol,1}}, ::Symbol, ::Symbol) at ./REPL[28]:27
in degree(::Array{Symbol,1}, ::Array{Tuple{Symbol,Symbol},1}, ::Symbol, ::Symbol) at ./REPL[30]:1