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

0.5.0

(Ä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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow