Julia Language
podczas gdy pętle
Szukaj…
Składnia
- podczas cond; ciało; koniec
- przerwa
- kontyntynuj
Uwagi
while
pętla nie ma wartości; chociaż można go użyć w pozycji wyrażenia, jego typ to Void
a uzyskana wartość będzie nothing
.
Sekwencja Collatz
while
pętla uruchamia swoje ciało dopóki warunek jest spełniony. Na przykład poniższy kod oblicza i drukuje sekwencję Collatz z podanej liczby:
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
Stosowanie:
julia> collatz(10)
10
5
16
8
4
2
1... and 4, 2, 1, 4, 2, 1 and so on
Możliwe jest zapisywanie dowolnej pętli rekurencyjnie, a dla złożonych pętli while
czasami wariant rekurencyjny jest bardziej przejrzysty. Jednak w Julii pętle mają pewne wyraźne zalety w stosunku do rekurencji:
- Julia nie gwarantuje eliminacji wywołania ogona, więc rekurencja zużywa dodatkową pamięć i może powodować błędy przepełnienia stosu.
- Co więcej, z tego samego powodu, pętla mogła zmniejszyć obciążenie i działać szybciej.
Uruchom raz przed przetestowaniem warunku
Czasami ktoś chce uruchomić kod inicjalizacyjny raz przed przetestowaniem warunku. W niektórych innych językach ten rodzaj pętli ma specjalną składnię do
- while
. Jednak ta składnia można zastąpić regularnych while
pętli i break
rachunku, więc Julia nie specjalizuje się do
- while
składnię. Zamiast tego pisze się:
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
Zauważ, że w niektórych sytuacjach pętle takie mogą być wyraźniejsze w przypadku rekurencji:
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
Pierwsze wyszukiwanie szerokości
(Chociaż ten przykład został napisany przy użyciu składni wprowadzonej w wersji v0.5, może również działać z kilkoma modyfikacjami w starszych wersjach).
Ta implementacja pełnego wyszukiwania (BFS) na wykresie reprezentowanym przez listy przyległości używa pętli while
i instrukcji return
. Zadanie, które rozwiążemy, jest następujące: mamy sekwencję ludzi i sekwencję przyjaźni (przyjaźnie są wzajemne). Chcemy określić stopień połączenia między dwojgiem ludzi. To znaczy, jeśli dwie osoby są przyjaciółmi, zwrócimy 1
; jeśli jeden jest przyjacielem drugiego, zwrócimy 2
i tak dalej.
Po pierwsze, załóżmy, że mamy już listę przylegania: Dict
odwzorowujący T
na Array{T, 1}
, gdzie kluczami są ludzie, a wartości wszyscy przyjaciele tej osoby. Tutaj możemy reprezentować osoby z dowolnym typem T
który wybieramy; w tym przykładzie użyjemy Symbol
. W algorytmie BFS utrzymujemy kolejkę osób do „odwiedzenia” i zaznaczamy ich odległość od węzła źródłowego.
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
Teraz napiszemy funkcję budowania listy sąsiedztwa, biorąc pod uwagę sekwencję ludzi i sekwencję krotek (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
Możemy teraz zdefiniować oryginalną funkcję:
degree(people, friendships, source, dest) =
degree(makeadjlist(people, friendships), source, dest)
Teraz przetestujmy naszą funkcję na niektórych danych.
const people = [:jean, :javert, :cosette, :gavroche, :éponine, :marius]
const friendships = [
(:jean, :cosette),
(:jean, :marius),
(:cosette, :éponine),
(:cosette, :marius),
(:gavroche, :éponine)
]
Jean jest połączony z sobą w 0
krokach:
julia> degree(people, friendships, :jean, :jean)
0
Jean i Cosette są przyjaciółmi, więc mają stopień 1
:
julia> degree(people, friendships, :jean, :cosette)
1
Jean i Gavroche są połączeni pośrednio przez Cosette, a następnie Marius, więc ich stopień wynosi 3
:
julia> degree(people, friendships, :jean, :gavroche)
3
Javert i Marius nie są połączeni żadnym łańcuchem, więc pojawia się błąd:
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