Zoeken…


Syntaxis

  • terwijl cond; lichaam; einde
  • breken
  • doorgaan met

Opmerkingen

De while lus heeft geen waarde; hoewel het in de expressiepositie kan worden gebruikt, is het type Void en is de verkregen waarde nothing .

Collatz-reeks

De while lus loopt door zijn lichaam zolang de toestand van kracht is. Met de volgende code wordt bijvoorbeeld de Collatz-reeks berekend en afgedrukt vanaf een bepaald 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

Gebruik:

julia> collatz(10)
10
5
16
8
4
2
1... and 4, 2, 1, 4, 2, 1 and so on

Het is mogelijk om elke lus recursief te schrijven, en voor complexe while lussen is de recursieve variant soms duidelijker. In Julia hebben loops echter een aantal duidelijke voordelen ten opzichte van recursie:

  • Julia garandeert geen eliminatie van staartoproepen, dus recursie gebruikt extra geheugen en kan stapeloverloopfouten veroorzaken.
  • En verder, om dezelfde reden, kan een lus minder overhead hebben en sneller lopen.

Voer één keer uit voordat de conditie wordt getest

Soms wil men eenmaal een initialisatiecode uitvoeren voordat een voorwaarde wordt getest. In bepaalde andere talen heeft dit soort lus een speciale do - while syntaxis. Deze syntaxis kan echter worden vervangen door een reguliere while lus en break instructie, dus Julia heeft geen gespecialiseerde do - while syntaxis. In plaats daarvan schrijft men:

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

Merk op dat in sommige situaties dergelijke lussen duidelijker kunnen zijn met recursie:

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

Breedte-eerste zoekopdracht

0.5.0

(Hoewel dit voorbeeld is geschreven met behulp van syntaxis geïntroduceerd in versie v0.5, kan het ook met enkele wijzigingen werken op oudere versies.)

Deze implementatie van breedte-eerste zoekopdracht (BFS) in een grafiek die wordt weergegeven met aangrenzende lijsten maakt gebruik van while lussen en de return instructie. De taak die we zullen oplossen is als volgt: we hebben een opeenvolging van mensen en een opeenvolging van vriendschappen (vriendschappen zijn wederzijds). We willen de mate van verbinding tussen twee mensen bepalen. Dat wil zeggen, als twee mensen vrienden zijn, zullen we 1 teruggeven; als de een vriend is van een vriend van de ander, zullen we 2 teruggeven, enzovoort.

Laten we eerst aannemen dat we al een aangrenzende lijst hebben: een Dict T aan Array{T, 1} , waarbij de sleutels mensen zijn en de waarden alle vrienden van die persoon zijn. Hier kunnen we mensen vertegenwoordigen met het type T we kiezen; in dit voorbeeld gebruiken we Symbol . In het BFS-algoritme houden we een rij mensen bij om te 'bezoeken' en markeren ze hun afstand tot het oorspronkelijke knooppunt.

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 zullen we een functie schrijven om een aangrenzende lijst samen te stellen met een reeks mensen en een reeks (person, person) tupels:

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

We kunnen nu de oorspronkelijke functie definiëren:

degree(people, friendships, source, dest) =
    degree(makeadjlist(people, friendships), source, dest)

Laten we nu onze functie op enkele gegevens testen.

const people = [:jean, :javert, :cosette, :gavroche, :éponine, :marius]
const friendships = [
    (:jean, :cosette),
    (:jean, :marius),
    (:cosette, :éponine),
    (:cosette, :marius),
    (:gavroche, :éponine)
]

Jean is in 0 stappen met zichzelf verbonden:

julia> degree(people, friendships, :jean, :jean)
0

Jean en Cosette zijn vrienden, en hebben dus ook graad 1 :

julia> degree(people, friendships, :jean, :cosette)
1

Jean en Gavroche zijn indirect verbonden via Cosette en vervolgens Marius, dus hun graad is 3 :

julia> degree(people, friendships, :jean, :gavroche)
3

Javert en Marius zijn via geen enkele ketting verbonden, dus er is een fout opgetreden:

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow