From: "akr (Akira Tanaka) via ruby-core" Date: 2023-09-24T13:43:13+00:00 Subject: [ruby-core:114894] [Ruby master Feature#13933] Add Range#empty? Issue #13933 has been updated by akr (Akira Tanaka). Dan0042 (Daniel DeLorme) wrote in #note-9: > akr (Akira Tanaka) wrote in #note-8: > > Range#empty? should work with them. > > Ok for `Float::INFINITY, [], ""`, but I don't think `true, false, Object.new` are relevant. A Range object normally has a begin and end, and if the values are not comparable (like `"a"..1`) we get "ArgumentError (bad value for range)". With `true..true` we happen to coincidentally pass that validation because `true<=>true` is 0 (and arguably it should be nil but that's another topic). But semantically, as a range, `true..true` doesn't mean anything. The introduction of beginless/endless ranges also mean that we can now create all kinds of ranges that skip the normal validation. > > `(true..true)` and `(true..)` and `(..true)` are not semantically meaningful ranges, there is no use case for them, and therefore it doesn't matter that `#include?` raises an error, and it shouldn't matter what is returned by `#empty?` There is an actual example of `(x <=> x) = nil`, `Float::NAN`. ``` % ruby -e 'x = Float::NAN; p x <=> x' nil ``` From experience with `Float::NAN`, I think it is not a good idea to expand such objects. It makes the behavior of `Array#<=>` inconsistent. ``` % ruby -e 'a = [Float::NAN]; p a <=> a' 0 ``` Since the (only) element of the array, `Float::NAN`, is not comparable, the array should not be comparable. But `a <=> a` returns 0 which means it is comparable and equal. It is because `Array#<=>` returns 0 if the given argument is the receiver itself, regardless of its elements. We need to choose efficiency or consistency. Ruby chooses efficiency here: `Array#<=>` returns 0 without examining its elements. Expanding `Floag::NAN`'like behavior makes this inconsistency more visible. I agree that objects comparable only with itself have not much usage for range. But their order is well-defined as a partial order. There is no reason to break it. > But unlike `true`, arrays truly are comparable. The Comparable module is not mixed in, but <=> can return -1 and 1. So `[]` is truly a minimum value for arrays. It could be special-cased. Although I'm not sure it's worth the trouble. Or maybe we can define a range "r" as empty if `r.begin.nil? and r.exclude_end? and r.end.respond_to?(:empty?) and r.end.empty?` You ignored the user-defined classes I mentioned. A user may define a class with a minimum value. The minimum value may not have `empty?` method. ---------------------------------------- Feature #13933: Add Range#empty? https://bugs.ruby-lang.org/issues/13933#change-104752 * Author: ted (Ted Johansson) * Status: Open * Priority: Normal ---------------------------------------- Range already responds to #size. It would be nice if it also responded to predicate #empty? :-) -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/