LoginSignup
5
5

More than 5 years have passed since last update.

Arrayにある見えない配列

Posted at

結論

先に結論を書いておくと、以下で言われてることと同じ内容だった。

忘れそうなのでメモとして残しておく。

発端

予め定義された配列を部分的に扱うために、Arrayを継承したHogeクラスを作成しようとした。
具体的には、

  • Hogeクラスは予め定義された配列を持っている
  • newすると予め定義された配列の部分配列を返す
  • newするときにoptionとして、afterとlimitを渡せる
    • after : 予め定義された配列の先頭要素
    • limit : 返す部分配列の要素数
  • nextで次の部分配列をlimit分返してくれる

作ったクラス

ざっと以下のような感じ。

class Hoge < Array
  ATOE = ["a", "b", "c"]
  DEFAULT_LIMIT = 3 
  DEFAULT_AFTER = 0 

  def initialize(options={})
    limit = (options[:limit] && options[:limit] > 0) ? options[:limit] : DEFAULT_LIMIT
    after = (options[:after] && options[:after] > 0) ? options[:after] : DEFAULT_AFTER
    st = after
    ed = after + limit - 1 
    super(ATOE[st..ed])
    @limit = limit
    @after = after
  end 

  def next
    options = { limit: @limit, after: @after + @limit }
    Hoge.new(options)
  end 
end

見えない配列とnil

使ってみると不思議な現象に遭遇。

hoge = Hoge.new(limit: 1, after: 0)
hoge              #=> ["a"]
hoge = hoge.next  #=> ["b"]
hoge = hoge.next  #=> ["c"]
hoge = hoge.next  #=> []
hoge = hoge.next  #=> `initialize': no implicit conversion from nil to integer (TypeError)

エラーはArray.new(nil)したらしい・・・。
しかしその前の空配列は何・・・?

Arrayで確認。ふぉー。

ary = []
ary[0..0]  #=> [] 
ary[1..1]  #=> nil 
ary[0..1]  #=> []
ary[1..2]  #=> nil

ary = ["a"]
ary[1..1]  #=> [] 
ary[2..2]  #=> nil 
ary[1..2]  #=> []
ary[2..3]  #=> nil

ggってみたところ、記事先頭のリンク先のように、謎の要素があるらしい。
なので、

super(ATOE[st..ed]||[])

にして解決。

ちなみに、[]はsliceの別名メソッドなので、slice使った場合も同様。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5