The range and the puzzles that it covers are out of my range

Am I trying to understand how range.cover? works range.cover? and the following seems confusing -

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

    This example is not confused in isolation, as it looks like a valued word style, where ass precedes at , followed by ate .

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

    This truth seems to be based on ASCII values, and not on dictionary style, because in the dictionary I expect all special characters to precede even numbers, and the confusion begins here. If what I think is true, then how is cover? decide which comparison method to use, that is, use ASCII values ​​or a dictionary-based approach.

  • And how the range works with arrays. For instance -

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

    In this example, I expected to be false. But at first glance it looks like that when working with arrays, the boundary values, as well as the cover? argument cover? are converted to a string, and a simple dictionary dictionary comparison gives true. Is this the correct interpretation?

  • What Range objects are equipped for processing? I know that it can accept numbers (except complex ones), handle strings , can work mystically with arrays , while boolean, nil and hash values ​​among others make it raise ArgumentError: bad value for range

+4
source share
1 answer

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

Let take a look at the source . In Ruby 1.9.3, we can see the following definition.

 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; } 

If the beginning of the range is not less than or equal to the specified value of cover? returns false . Here, lesser or equal is defined in terms of the r_lt function, which uses the <=> operator for comparison. Let's see how it behaves in the case of arrays

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

Thus, obviously, [1] really smaller [9,11,335] . As a result, we enter the body of the first if . Internally, we check to see if the range excludes its end and performs a second comparison using the <=> operator again.

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

Therefore, [10] greater than [9,11,335] . The method returns true .

Why do you see ArgumentError: bad value for range

The function responsible for raising this error is range_failed . It is called only when range_check returns a nil . When does this happen? When the beginning and end of the range are incomparable (yes, again from the point of view of our dear friend, the operator <=> ).

 true <=> false # => nil 

true and false comparable. Range cannot be created and ArgumentError raised.

In a final note, the Range.cover? dependency Range.cover? from <=> is actually expected and documented behavior. See the RubySpec specification for cover? .

+4
source

Source: https://habr.com/ru/post/1440856/


All Articles