新しいsliceのまとめ

従来の、selfと同じ型を返すslice([pos len])がslice_safe({pos len})になり、sliceはRangeを返すようになりました。
大きな配列や文字列を扱う場合にかなりの高速化とメモリ使用量抑制が期待できますが、注意点もあります。

Rangeに関する注意

sliceに限らない、Range全般の注意が当てはまります。位置情報ではなく、イテレータを持つだけですので、その参照先に変化が有った場合に不正な参照になりえます。

s:: 'abc'
r: s.[1 1] //== 'b'
s.resize(10) //reallocation
r.join //結果不明

元の型との互換性は基本的はありません。Containerにより一般化されることでContainerの子のメソッドの客体にはなれますが、主体にはなれません。

s:: 'abc'
r: s.[1 1] //== 'b'
s.+ r //'abcb'
r.+ s //error

ランダムアクセスイテレータ

引数のpos(位置)とlen(長さ)の計算にはself.sizeやself.begin.<などが使われるため、イテレータがそれらに対応してなければいけません。(ランダムアクセスイテレータ)
たとえば、Path.dirの返すRangeのイテレータはDirectory_iteratorであり、これはランダムアクセスではありませんので、sliceには使えませんが、slice_safeはself.deep_copy.slice!で、Range.deep_copyはArrayを返すので、Path.dir.{pos len}はArrayを返すことで機能します。

slice!とRange

slice!([pos len]!)とslice_safe!({pos len}!)の違いは、Rangeの場合にslice!は機能し、slice_safe!はエラーになることです。性能差はほとんど無いので、slice_safe!の側の無駄な制限のようにも思えます。