Julia Language
medan Loops
Sök…
Syntax
- medan kond; kropp; slutet
- ha sönder
- Fortsätta
Anmärkningar
while
slingan har inget värde; även om det kan användas i uttrycksposition är dess typ Void
och det erhållna värdet blir nothing
.
Collatz-sekvens
while
slingan kör sin kropp så länge tillståndet rymmer. Till exempel beräknar och skriver ut följande kod Collatz-sekvensen från ett givet nummer:
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
Användande:
julia> collatz(10)
10
5
16
8
4
2
1... and 4, 2, 1, 4, 2, 1 and so on
Det är möjligt att skriva valfri loop rekursivt, och för komplexa while
loppar, ibland är den rekursiva varianten mer tydlig. Men i Julia har slingor vissa distinkta fördelar jämfört med rekursion:
- Julia garanterar inte eliminering av svanssamtal, så rekursion använder extra minne och kan orsaka stackoverflödesfel.
- Och av samma anledning kan en slinga ha minskat över huvudet och kör snabbare.
Kör en gång innan du testar tillståndet
Ibland vill man köra någon initialiseringskod en gång innan man testar ett tillstånd. I vissa andra språk, har denna typ av slinga special do
- while
syntax. Emellertid kan denna syntax ersättas med ett vanligt while
loop och break
uttalande, så Julia har inte specialiserat do
- while
syntax. Istället skriver man:
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
Observera att i vissa situationer kan sådana öglor vara tydligare med rekursion:
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
Utöka första sökningen
(Även om det här exemplet skrivs med syntax som introducerats i version v0.5, kan det fungera med få ändringar på äldre versioner också.)
Denna implementering av bredd-först-sökning (BFS) på en graf representerade med adjacency listor användningsområden while
loopar och return
uttalande. Uppgiften vi kommer att lösa är som följer: vi har en sekvens av människor och en sekvens av vänskap (vänskap är inbördes). Vi vill bestämma graden av sambandet mellan två personer. Det vill säga om två personer är vänner kommer vi tillbaka 1
; om en är en vän till en vän till den andra, kommer vi tillbaka 2
, och så vidare.
Låt oss först anta att vi redan har en adjacenslista: en Dict
kartlägger T
till Array{T, 1}
, där nycklarna är människor och värdena är alla vänner till den personen. Här kan vi representera människor med vilken typ T
vi väljer; i det här exemplet kommer vi att använda Symbol
. I BFS-algoritmen håller vi en kö av människor för att "besöka" och markerar deras avstånd från ursprungsnoden.
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
Nu kommer vi att skriva en funktion för att bygga en adjacenslista med tanke på en sekvens av personer och en sekvens av (person, person)
tuples:
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
Vi kan nu definiera den ursprungliga funktionen:
degree(people, friendships, source, dest) =
degree(makeadjlist(people, friendships), source, dest)
Låt oss nu testa vår funktion på vissa data.
const people = [:jean, :javert, :cosette, :gavroche, :éponine, :marius]
const friendships = [
(:jean, :cosette),
(:jean, :marius),
(:cosette, :éponine),
(:cosette, :marius),
(:gavroche, :éponine)
]
Jean är ansluten till sig själv i 0
steg:
julia> degree(people, friendships, :jean, :jean)
0
Jean och Cosette är vänner, och så har grad 1
:
julia> degree(people, friendships, :jean, :cosette)
1
Jean och Gavroche är indirekt anslutna via Cosette och sedan Marius, så deras grad är 3
:
julia> degree(people, friendships, :jean, :gavroche)
3
Javert och Marius är inte anslutna genom någon kedja, så ett fel tas upp:
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