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

0,5.0

(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


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow