index(Object.[x])やslice(Object.[x y])について

配列(Array)や連想配列(Map)や文字列(String)を扱うための構文糖(シンタクスシュガー)、[]構文の解説です。
角括弧内の引数の数が1つならindex、2つならsliceとなり、それに加え、角括弧に=が付くと*_setとなります。

s: 'abcedfg'
s.[0] //s.index(0)
s.[0 1] //s.slice(0 1)
s.[1] = \A //s.index_set(1 \A)
s.[1 2] = (\A \B) //s.slice_set(1 2 \A \B)

index

数値が負数の場合、"要素数 + 負数"となります。その結果も負数の場合は、要素数より値が大きい場合と同じくエラーになります。

'abcedfg'.[0] //\a
'abcedfg'.[1] //\b
{10 20 30}.[2] //30
Map.new(\a.=> 1 \b.=> 2 \c.=> 3).[\b] //2

'abcedfg'.[-1] //\g
{10 20 30}.[3] //エラー

連想配列に対して存在しないキーを指定した場合は、そのキーが作成され、初期値であるNULLオブジェクトが返ります。

Map.new(\a.=> 1 \b.=> 2 \c.=> 3).[\d] //NULL (アクセスすると強制終了)

index_set

indexメソッドの戻り値に対し、内部的に、直接、代入演算子を発動します。ArrayやMapの値の初期値はNULLオブジェクトであるため、indexの戻り値の代入演算子の呼び出しは不可能であり、index_setが必要になります。

s:: 'abcedfg' //s: 'abcdefg'.copy
s.[0] = \A //s.[0].= \A と結果は同じだが、index_setのほうが直接的であるため速い
s.== 'Abcdefg'

a: {10 20 30}
a.resize(4)
a.[3] = 40 //a.[3].= 40 ではa.[3]の戻り値であるNULLオブジェクトの=メソッドを呼び出そうとするため強制終了することになる
a.== {10 20 30 40}

m: Map.new(\a.=> 1 \b.=> 2 \c.=> 3)
m.[\d] = 4 //m.[\d].= 4 ではm.[\d]の戻り値であるNULLオブジェクトの=メソッドを呼び出そうとするため強制終了することになる
m.[\d].== 4

slice

引数は、[position count]となります。戻り値は、positionからcount数の値を有したselfと同じ型のオブジェクトです。値が負数の場合はindexと同じ扱いです。数値が過大な場合は、要素数扱いとなります。連想配列(Map)には使用できません。

'abcdefg'.[2 3] //'cde'
'abcdefg'.[2 -1] //'cdef'
'abcdefg'.[-5 3] //'cde'
'abcdefg'.[10 3] //''
'abcdefg'.[1 Uint.max_limit] //'bcdefg'

slice!

Rubyと違い、selfをsliceの戻り値にします。(同じようにするには、slice_setを使います。)

s:: 'abcdefg'
s.[2 3]!
s.== 'cde'

slice_set

指定された部分をself.eraseで消し、その位置に代入演算子右辺の値をself.insertで挿入します。右辺には複数の値を置けます。右辺に配列等を置いても、数値等を置いた場合と動作が変わることはありません。

s:: 'abcdefg'
s.[2 3] = \-
s.== 'ab-fg'

s:: 'abcdefg'
s.[2 3] = 'ABCDEFG' //String.insertは文字列を受け取れる
s.== 'abABCDEFGfg'

s:: 'abcdefg'
s.[2 3] = (\- \= \-) //複数の右辺引数
s.== 'ab-=-fg'

s:: 'abcdefg'
s.[2 3] = () //右辺引数がゼロならinsertは呼ばれず、Rubyのslice!と同じ結果になる
s.== 'abfg'