4

私はどのようにrange.cover?機能するかを理解しようとしていますが、以下は混乱しているようです-

  1. ("as".."at").cover?("ass") # true("as".."at").cover?("ate") # false

    assこの例を単独で見ると、が前に来て がat続く辞書スタイルで評価されるように見えるため、混乱することはありませんate

  2. ("1".."z").cover?(":") # true

    この真実は、辞書スタイルではなく ASCII 値に基づいているようです。辞書では、すべての特殊文字が偶数の数字の前にあると予想され、混乱はここから始まるからです。私が思うことが本当ならcover?、採用する比較方法、つまりASCII値または辞書ベースのアプローチを使用する方法をどのように決定しますか。

  3. そして、範囲は配列でどのように機能しますか。例えば ​​-

    ([1]..[10]).cover?([9,11,335]) # true

    この例は、私は間違っていると思っていました。cover?しかし、一見すると、配列を扱う場合、境​​界値との引数が文字列に変換され、単純な辞書スタイルの比較で true が返されるように見えます。それは正しい解釈ですか?

  4. どのようなオブジェクトRangeを処理するために装備されていますか? 私はそれが取ることができることを知っていますnumbers(複雑なものを除く), ハンドル,とりわけ値がそれを発生させる間、strings神秘的に動作することができますarraysboolean, nil and hashArgumentError: bad value for range

4

1 に答える 1

4

なぜ([1]..[10]).cover?([9,11,335])戻るtrue

ソースを見てみましょう。Ruby 1.9.3 では、次の定義を見ることができます。

static VALUE
range_cover(VALUE range, VALUE val)
{
  VALUE beg, end;

  beg = RANGE_BEG(range);
  end = RANGE_END(range);
  if (r_le(beg, val)) {
    if (EXCL(range)) {
      if (r_lt(val, end))
        return Qtrue;
    }
    else {
      if (r_le(val, end))
        return Qtrue;
    }
  }
  return Qfalse;
}

範囲の先頭が指定された値以下でない場合は、 がcover?返されますfalse。ここで、比較のために演算子を使用する関数の観点から、より小さいか等しいかが決定されます。配列の場合にどのように動作するか見てみましょうr_lt<=>

[1] <=> [9,11,335] # => -1

どうやら[1]は実際に よりも小さいようです[9,11,335]。その結果、最初の の本体に入りifます。内部では、範囲がその末尾を除外しているかどうかを確認し、もう一度<=>演算子を使用して 2 回目の比較を行います。

[10] <=> [9,11,335] # => 1

したがって[10]、 より大きいです[9,11,335]。メソッドは を返しますtrue

なぜあなたは見るのですかArgumentError: bad value for range

このエラーの原因となっている機能はrange_failed. range_checkが a を返す場合にのみ呼び出されますnil。それはいつ起こりますか?<=>範囲の開始と終了が比較できない場合 (はい、親愛なる友人であるオペレーターに関してもう一度言います)。

true <=> false # => nil

trueそしてfalse比類のないものです。範囲を作成できず、ArgumentErrorが発生します。

最後に、Range.cover?の への依存<=>は、実際には予想され、文書化された動作です。RubySpecの の仕様をcover?参照してください。

于 2012-10-19T18:52:29.757 に答える