范围和它涵盖的神秘范围超出我的范围

时间:2012-10-19 18:31:06

标签: ruby range

我想了解range.cover?如何运作,以下似乎令人困惑 -

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

    这个孤立的例子并不令人困惑,因为它似乎是assat之前跟ate之前的字典样式。

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

    这个事实似乎是基于ASCII值而不是字典样式,因为在字典中我希望所有特殊字符都在数字之前,并且混乱从这里开始。如果我认为是真的那么cover?如何决定采用哪种比较方法,即使用ASCII值或基于字典的方法。

  3. 范围如何与数组一起使用。例如 -

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

    这个例子我预计是假的。但是从表面看来,在处理数组时,边界值以及cover?的参数都会转换为字符串,而简单的字典样式比较会产生真值。这是正确的解释吗?

  4. Range有哪些物品需要处理?我知道它可以numbers(复杂的除外),处理strings,能够神秘地使用arrays,而boolean, nil and hash值会导致它ArgumentError: bad value for range }

1 个答案:

答案 0 :(得分:4)

为什么([1]..[10]).cover?([9,11,335])会返回true

让我们take a look at the source。在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函数确定的,range_failed函数使用<=>运算符进行比较。让我们看看它在数组

的情况下是如何表现的
[1] <=> [9,11,335] # => -1

显然[1]确实小于[9,11,335]。结果我们进入了第一个if的主体。我们在内部检查范围是否排除其结束并再次使用<=>运算符进行第二次比较。

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

因此[10]大于[9,11,335]。该方法返回true

为什么看到ArgumentError: bad value for range

负责引发此错误的函数是RubySpec。仅在range_check返回nil时才会调用它。它什么时候发生?当范围的开始和结束是无法比较的(是的,再一次是我们亲爱的朋友,<=>运营商)。

true <=> false # => nil

truefalse无法比较。无法创建范围并引发ArgumentError

在结束语中,Range.cover?<=>的依赖实际上是预期和记录的行为。请参阅specification of cover?&#39; {{3}}。