Feature #11286 » 0001-enum.c-add-case-equality-arity-to-sequence-predicates.patch
ChangeLog | ||
---|---|---|
Fri Jun 19 16:10:22 2015 D.E. Akers <0x0dea@gmail.com>
|
||
* enum.c: add case equality arity to sequence predicates.
|
||
* test/ruby/test_enum.rb: add tests for above.
|
||
Fri Jun 19 14:53:35 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||
* proc.c (rb_mod_define_method): now requires a block direct to
|
enum.c | ||
---|---|---|
return ary;
|
||
}
|
||
#define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
|
||
#define ENUMFUNC(name, argc) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
|
||
#define DEFINE_ENUMFUNCS(name) \
|
||
static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
|
||
... | ... | |
} \
|
||
\
|
||
static VALUE \
|
||
name##_eqq(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
|
||
{ \
|
||
return enum_##name##_func(rb_funcall(MEMO_CAST(memo)->v2, id_eqq, 1, i), MEMO_CAST(memo)); \
|
||
} \
|
||
\
|
||
static VALUE \
|
||
enum_##name##_func(VALUE result, struct MEMO *memo)
|
||
DEFINE_ENUMFUNCS(all)
|
||
... | ... | |
/*
|
||
* call-seq:
|
||
* enum.all? [{ |obj| block } ] -> true or false
|
||
* enum.all?(pattern) -> true or false
|
||
*
|
||
* Passes each element of the collection to the given block. The method
|
||
* returns <code>true</code> if the block never returns
|
||
... | ... | |
* cause #all? to return +true+ when none of the collection members are
|
||
* +false+ or +nil+.
|
||
*
|
||
* If instead a pattern is supplied, the method returns whether
|
||
* <code>pattern === element</code> for every element of <i>enum</i>.
|
||
*
|
||
* %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
|
||
* %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
|
||
* %w[ant bear cat].all?(/t/) #=> false
|
||
* [1, 2i, 3.14].all?(Numeric) #=> true
|
||
* [nil, true, 99].all? #=> false
|
||
*
|
||
*/
|
||
static VALUE
|
||
enum_all(VALUE obj)
|
||
enum_all(int argc, VALUE *argv, VALUE obj)
|
||
{
|
||
struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
|
||
struct MEMO *memo = MEMO_NEW(Qtrue, *argv, 0);
|
||
rb_check_arity(argc, 0, 1);
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all, argc), (VALUE)memo);
|
||
return memo->v1;
|
||
}
|
||
... | ... | |
/*
|
||
* call-seq:
|
||
* enum.any? [{ |obj| block }] -> true or false
|
||
* enum.any?(pattern) -> true or false
|
||
*
|
||
* Passes each element of the collection to the given block. The method
|
||
* returns <code>true</code> if the block ever returns a value other
|
||
... | ... | |
* will cause #any? to return +true+ if at least one of the collection
|
||
* members is not +false+ or +nil+.
|
||
*
|
||
* If instead a pattern is supplied, the method returns whether
|
||
* <code>pattern === element</code> for any element of <i>enum</i>.
|
||
*
|
||
* %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
|
||
* %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
|
||
* %w[ant bear cat].any?(/d/) #=> false
|
||
* [nil, true, 99].any? #=> true
|
||
* [nil, true, 99].any?(Float) #=> false
|
||
*
|
||
*/
|
||
static VALUE
|
||
enum_any(VALUE obj)
|
||
enum_any(int argc, VALUE *argv, VALUE obj)
|
||
{
|
||
struct MEMO *memo = MEMO_NEW(Qfalse, 0, 0);
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
|
||
struct MEMO *memo = MEMO_NEW(Qfalse, *argv, 0);
|
||
rb_check_arity(argc, 0, 1);
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any, argc), (VALUE)memo);
|
||
return memo->v1;
|
||
}
|
||
... | ... | |
/*
|
||
* call-seq:
|
||
* enum.one? [{ |obj| block }] -> true or false
|
||
* enum.one?(pattern) -> true or false
|
||
*
|
||
* Passes each element of the collection to the given block. The method
|
||
* returns <code>true</code> if the block returns <code>true</code>
|
||
... | ... | |
* <code>true</code> only if exactly one of the collection members is
|
||
* true.
|
||
*
|
||
* If instead a pattern is supplied, the method returns whether
|
||
* <code>pattern === element</code> for exactly one element of <i>enum</i>.
|
||
*
|
||
* %w{ant bear cat}.one? { |word| word.length == 4 } #=> true
|
||
* %w{ant bear cat}.one? { |word| word.length > 4 } #=> false
|
||
* %w{ant bear cat}.one? { |word| word.length < 4 } #=> false
|
||
* %w{ant bear cat}.one?(/t/) #=> false
|
||
* [ nil, true, 99 ].one? #=> false
|
||
* [ nil, true, false ].one? #=> true
|
||
* [ nil, true, 99 ].one?(Fixnum) #=> true
|
||
*
|
||
*/
|
||
static VALUE
|
||
enum_one(VALUE obj)
|
||
enum_one(int argc, VALUE *argv, VALUE obj)
|
||
{
|
||
struct MEMO *memo = MEMO_NEW(Qundef, 0, 0);
|
||
struct MEMO *memo = MEMO_NEW(Qundef, *argv, 0);
|
||
VALUE result;
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
|
||
rb_check_arity(argc, 0, 1);
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one, argc), (VALUE)memo);
|
||
result = memo->v1;
|
||
if (result == Qundef) return Qfalse;
|
||
return result;
|
||
... | ... | |
/*
|
||
* call-seq:
|
||
* enum.none? [{ |obj| block }] -> true or false
|
||
* enum.none?(pattern) -> true or false
|
||
*
|
||
* Passes each element of the collection to the given block. The method
|
||
* returns <code>true</code> if the block never returns <code>true</code>
|
||
* for all elements. If the block is not given, <code>none?</code> will return
|
||
* <code>true</code> only if none of the collection members is true.
|
||
*
|
||
* If instead a pattern is supplied, the method returns whether
|
||
* <code>pattern === element</code> for none of the elements of <i>enum</i>.
|
||
*
|
||
* %w{ant bear cat}.none? { |word| word.length == 5 } #=> true
|
||
* %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
|
||
* %w{ant bear cat}.none?(/d/) #=> true
|
||
* [].none? #=> true
|
||
* [nil].none? #=> true
|
||
* [nil, false].none? #=> true
|
||
* [nil, false].none?(NilClass) #=> false
|
||
*/
|
||
static VALUE
|
||
enum_none(VALUE obj)
|
||
enum_none(int argc, VALUE *argv, VALUE obj)
|
||
{
|
||
struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
|
||
struct MEMO *memo = MEMO_NEW(Qtrue, *argv, 0);
|
||
rb_check_arity(argc, 0, 1);
|
||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none, argc), (VALUE)memo);
|
||
return memo->v1;
|
||
}
|
||
... | ... | |
rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
|
||
rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
|
||
rb_define_method(rb_mEnumerable, "first", enum_first, -1);
|
||
rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
|
||
rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
|
||
rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
|
||
rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
|
||
rb_define_method(rb_mEnumerable, "all?", enum_all, -1);
|
||
rb_define_method(rb_mEnumerable, "any?", enum_any, -1);
|
||
rb_define_method(rb_mEnumerable, "one?", enum_one, -1);
|
||
rb_define_method(rb_mEnumerable, "none?", enum_none, -1);
|
||
rb_define_method(rb_mEnumerable, "min", enum_min, -1);
|
||
rb_define_method(rb_mEnumerable, "max", enum_max, -1);
|
||
rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
|
test/ruby/test_enum.rb | ||
---|---|---|
assert_equal(false, @obj.all? {|x| x < 3 })
|
||
assert_equal(true, @obj.all?)
|
||
assert_equal(false, [true, true, false].all?)
|
||
assert_equal(true, @obj.all?(Fixnum))
|
||
assert_equal(false, @obj.all?(1..2))
|
||
end
|
||
def test_any
|
||
... | ... | |
assert_equal(false, @obj.any? {|x| x > 3 })
|
||
assert_equal(true, @obj.any?)
|
||
assert_equal(false, [false, false, false].any?)
|
||
assert_equal(true, @obj.any?(1..2))
|
||
assert_equal(false, @obj.any?(Float))
|
||
end
|
||
def test_one
|
||
assert(@obj.one? {|x| x == 3 })
|
||
assert(!(@obj.one? {|x| x == 1 }))
|
||
assert(!(@obj.one? {|x| x == 4 }))
|
||
assert(@obj.one?(3..4))
|
||
assert(!(@obj.one?(1..2)))
|
||
assert(!(@obj.one?(4..5)))
|
||
assert(%w{ant bear cat}.one? {|word| word.length == 4})
|
||
assert(!(%w{ant bear cat}.one? {|word| word.length > 4}))
|
||
assert(!(%w{ant bear cat}.one? {|word| word.length < 4}))
|
||
assert(%w{ant bear cat}.one?(/b/))
|
||
assert(!(%w{ant bear cat}.one?(/t/)))
|
||
assert(!([ nil, true, 99 ].one?))
|
||
assert([ nil, true, false ].one?)
|
||
assert([nil, true, 99].one?(NilClass))
|
||
end
|
||
def test_none
|
||
assert(@obj.none? {|x| x == 4 })
|
||
assert(!(@obj.none? {|x| x == 1 }))
|
||
assert(!(@obj.none? {|x| x == 3 }))
|
||
assert(@obj.none?(4..5))
|
||
assert(!(@obj.none?(1..3)))
|
||
assert(%w{ant bear cat}.none? {|word| word.length == 5})
|
||
assert(!(%w{ant bear cat}.none? {|word| word.length >= 4}))
|
||
assert(%w{ant bear cat}.none?(/d/))
|
||
assert(!(%w{ant bear cat}.none?(/b/)))
|
||
assert([].none?)
|
||
assert([nil].none?)
|
||
assert([nil,false].none?)
|