0以上の整数を1000まで全部使いたいとします。 それを配列にいちいち打ち込まなければならないとしたら、ばかげた話です。
そこで登場するのがrange型です。
julia> 0:1000
0:1000
julia> typeof(0:1000)
UnitRange{Int64}
範囲はとてもよく使われます。入力の手間を省くためだけでなく、関数の戻り値としても使われます。
範囲は_配列ではありません_。
配列は最初にまとめて作られ(「貪欲」な評価)、配列の長さに比例したメモリを必要とします。
それに対して範囲は、数列を生成するための手順の集まりにすぎません(「遅延」評価、つまり「イテレーター」です)。
範囲を配列として使いたいときは、collect()関数で変換します。
julia> collect(0:5)
6-element Vector{Int64}:
0
1
2
3
4
5
必要であれば、collect(type, range)を使って出力する配列の型を指定できます。
ステップ幅も指定できます。次の例では0.3です。
julia> collect(1.0:0.3:2.0)
4-element Vector{Float64}:
1.0
1.3
1.6
1.9
つまり、構文はstart:stepsize:stopです。
両端の値はどちらも_含まれます_。先ほどの整数の例でわかるとおりです。
ステップ幅がstop - startをちょうど割り切れない場合、最後の要素はstopを超えないようになります。
より細かく制御したいときは、Base.range()関数を使います。こちらにはさらに多くのオプションがあります。
範囲には、数値以外の並びも使えます。 もっとも簡単な例はASCII文字です。
julia> 'a':'d'
'a':1:'d'
julia> typeof('a':'d')
StepRange{Char, Int64}
julia> collect('a':'d')
4-element Vector{Char}:
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
Char型については、別のコンセプトで詳しく扱います。
今は、シングルクォートで囲んだ1文字だと考えておけば大丈夫です。
範囲の端の値は、first()とlast()で確認できます。
ある値が範囲に含まれているかどうかを調べることはよくあります。
そのための関数はin()ですが、中置演算子のinや、より数学的な同義語である∈を使うほうが一般的です。
対応するエディターでは、∈は\inと入力してからTabキーを押すと出せます。
r = 1:10 # => 1:10
first(r) # => 1
last(r) # => 10
7 in r # => true
11 ∈ r # => false
inや∈演算子は、ここでは範囲に対して使いましたが、ベクトル、集合、辞書など、ほかのさまざまなコレクション型にも使えます。
配列のインデックスには、整数の範囲や配列を使えます。
nums = collect(10.0:50.0)
nums[3:2:7] # gives [12.0, 14.0, 16.0]
nums[ [3, 5, 7] ] # also gives [12.0, 14.0, 16.0]
endと組み合わせて使うこともできますが、演算子の優先順位の関係で括弧(())が必要になることがあります。
nums[(end - 3):end]
4-element Vector{Float64}:
47.0
48.0
49.0
50.0
もちろん、インデックスの要素には、すでにある整数変数をどれでも使えます。