Julia Language
whileループ
サーチ…
構文
- 一方、cond。体;終わり
- ブレーク
- 持続する
備考
while
ループには値はありません。式の位置で使用することはできますが、その型はVoid
あり、得られた値はnothing
ありnothing
。
Collatzシーケンス
while
ループは、条件が成立する限り、その本体を実行します。たとえば、次のコードは、指定された数値からCollatzシーケンスを計算して出力します 。
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
使用法:
julia> collatz(10)
10
5
16
8
4
2
1... and 4, 2, 1, 4, 2, 1 and so on
任意のループを再帰的に記述することは可能であり、複雑なwhile
ループに対しては、再帰的な変形がより明確になることがあります。しかし、Juliaでは、ループは再帰よりもいくつかの明確な利点があります。
- Juliaはテールコールの消去を保証しません。したがって、再帰で追加のメモリが使用され、スタックオーバーフローエラーが発生する可能性があります。
- さらに、同じ理由で、ループがオーバーヘッドを減らし、より速く実行できるようになります。
テスト条件の前に一度実行する
場合によっては、条件をテストする前に初期化コードを一度実行したい場合もあります。ある種の他の言語では、この種のループには特別なdo
- while
構文がwhile
ます。ただし、この構文は通常のwhile
ループとbreak
文に置き換えることができます。そのため、Juliaには特別なdo
- while
構文はありません。代わりに、
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
状況によっては、このようなループが再帰でより明確になることがあります。
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
幅優先探索
(この例は、バージョンv0.5で導入された構文を使用して書かれていますが、古いバージョンでもほとんど変更されません)。
隣接リストで表されるグラフの幅優先検索 (BFS)のこの実装は、 while
ループとreturn
ステートメントを使用while
ます。私たちが解決する課題は、一連の人と一連の友情(友情は相互にあります)です。我々は2人の人のつながりの程度を判断したい。つまり、2人が友人であれば1
を返します。もし誰かが他の人の友人であれば、 2
を返します。
まず、隣接リストが既にあると仮定しましょう: Dict
T
をArray{T, 1}
にマッピングします。ここで、キーは人であり、値はその人のすべての友人です。ここでは、タイプT
を選んだ人を表すことができます。この例では、 Symbol
を使用します。 BFSアルゴリズムでは、人々の待ち行列を「訪問」し、起点ノードからの距離をマークする。
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
今度は、一連の人と一連の(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
これで元の関数を定義できます。
degree(people, friendships, source, dest) =
degree(makeadjlist(people, friendships), source, dest)
さて、いくつかのデータに対して私たちの関数をテストしましょう。
const people = [:jean, :javert, :cosette, :gavroche, :éponine, :marius]
const friendships = [
(:jean, :cosette),
(:jean, :marius),
(:cosette, :éponine),
(:cosette, :marius),
(:gavroche, :éponine)
]
ジーンは0
ステップで自分自身に接続されています:
julia> degree(people, friendships, :jean, :jean)
0
ジーンとコゼットは友達であり、学位1
ます:
julia> degree(people, friendships, :jean, :cosette)
1
JeanとGavrocheはCosetteとMariusを介して間接的に接続されているので、その程度は3
:
julia> degree(people, friendships, :jean, :gavroche)
3
JavertとMariusはチェーンを介して接続されていないので、エラーが発生します。
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