Add case equality arity to Enumerable#all?, any?, none? and one?,
and specialized Array#any? and Hash#any? Based on patch by D.E. Akers [#11286] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61098 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
86a794a6c3
commit
a9770bac63
4
NEWS
4
NEWS
@ -38,6 +38,10 @@ with all sufficient information, see the ChangeLog file or Redmine
|
|||||||
* Dir.children [Feature #11302]
|
* Dir.children [Feature #11302]
|
||||||
* Dir.each_child [Feature #11302]
|
* Dir.each_child [Feature #11302]
|
||||||
|
|
||||||
|
* Enumerable
|
||||||
|
|
||||||
|
* Enumerable#any?, all?, none? and one? now accept a pattern argument [Feature #11286]
|
||||||
|
|
||||||
* File
|
* File
|
||||||
|
|
||||||
* :newline option to File.open implies text mode now. [Bug #13350]
|
* :newline option to File.open implies text mode now. [Bug #13350]
|
||||||
|
12
array.c
12
array.c
@ -5771,13 +5771,19 @@ rb_ary_drop_while(VALUE ary)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_ary_any_p(VALUE ary)
|
rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
|
||||||
{
|
{
|
||||||
long i, len = RARRAY_LEN(ary);
|
long i, len = RARRAY_LEN(ary);
|
||||||
const VALUE *ptr = RARRAY_CONST_PTR(ary);
|
const VALUE *ptr = RARRAY_CONST_PTR(ary);
|
||||||
|
|
||||||
|
rb_check_arity(argc, 0, 1);
|
||||||
if (!len) return Qfalse;
|
if (!len) return Qfalse;
|
||||||
if (!rb_block_given_p()) {
|
if (argc) {
|
||||||
|
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||||
|
if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!rb_block_given_p()) {
|
||||||
for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
|
for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -6329,7 +6335,7 @@ Init_Array(void)
|
|||||||
rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
|
rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
|
||||||
rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
|
rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
|
||||||
rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
|
rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
|
||||||
rb_define_method(rb_cArray, "any?", rb_ary_any_p, 0);
|
rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
|
||||||
rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
|
rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
|
||||||
rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
|
rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
|
||||||
|
|
||||||
|
59
enum.c
59
enum.c
@ -1150,7 +1150,9 @@ enum_sort_by(VALUE obj)
|
|||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
|
#define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
|
||||||
|
|
||||||
|
#define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), MEMO_NEW((v1), (argc ? *argv : 0), 0))
|
||||||
|
|
||||||
#define DEFINE_ENUMFUNCS(name) \
|
#define DEFINE_ENUMFUNCS(name) \
|
||||||
static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
|
static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
|
||||||
@ -1168,6 +1170,13 @@ name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static VALUE \
|
static VALUE \
|
||||||
|
name##_eqq(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
|
||||||
|
{ \
|
||||||
|
ENUM_WANT_SVALUE(); \
|
||||||
|
return enum_##name##_func(rb_funcallv(MEMO_CAST(memo)->v2, id_eqq, 1, &i), MEMO_CAST(memo)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static VALUE \
|
||||||
enum_##name##_func(VALUE result, struct MEMO *memo)
|
enum_##name##_func(VALUE result, struct MEMO *memo)
|
||||||
|
|
||||||
DEFINE_ENUMFUNCS(all)
|
DEFINE_ENUMFUNCS(all)
|
||||||
@ -1182,6 +1191,7 @@ DEFINE_ENUMFUNCS(all)
|
|||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* enum.all? [{ |obj| block } ] -> true or false
|
* 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
|
* Passes each element of the collection to the given block. The method
|
||||||
* returns <code>true</code> if the block never returns
|
* returns <code>true</code> if the block never returns
|
||||||
@ -1190,17 +1200,22 @@ DEFINE_ENUMFUNCS(all)
|
|||||||
* cause #all? to return +true+ when none of the collection members are
|
* cause #all? to return +true+ when none of the collection members are
|
||||||
* +false+ or +nil+.
|
* +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 >= 3 } #=> true
|
||||||
* %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
|
* %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
|
* [nil, true, 99].all? #=> false
|
||||||
* [].all? #=> true
|
* [].all? #=> true
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
enum_all(VALUE obj)
|
enum_all(int argc, VALUE *argv, VALUE obj)
|
||||||
{
|
{
|
||||||
struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
|
struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
|
||||||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
|
||||||
return memo->v1;
|
return memo->v1;
|
||||||
}
|
}
|
||||||
@ -1217,6 +1232,7 @@ DEFINE_ENUMFUNCS(any)
|
|||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* enum.any? [{ |obj| block }] -> true or false
|
* 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
|
* Passes each element of the collection to the given block. The method
|
||||||
* returns <code>true</code> if the block ever returns a value other
|
* returns <code>true</code> if the block ever returns a value other
|
||||||
@ -1225,17 +1241,22 @@ DEFINE_ENUMFUNCS(any)
|
|||||||
* will cause #any? to return +true+ if at least one of the collection
|
* will cause #any? to return +true+ if at least one of the collection
|
||||||
* members is not +false+ or +nil+.
|
* 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 >= 3 } #=> true
|
||||||
* %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
|
* %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
|
||||||
|
* %w[ant bear cat].any?(/d/) #=> false
|
||||||
|
* [nil, true, 99].any?(Integer) #=> true
|
||||||
* [nil, true, 99].any? #=> true
|
* [nil, true, 99].any? #=> true
|
||||||
* [].any? #=> false
|
* [].any? #=> false
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
enum_any(VALUE obj)
|
enum_any(int argc, VALUE *argv, VALUE obj)
|
||||||
{
|
{
|
||||||
struct MEMO *memo = MEMO_NEW(Qfalse, 0, 0);
|
struct MEMO *memo = MEMO_ENUM_NEW(Qfalse);
|
||||||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
|
||||||
return memo->v1;
|
return memo->v1;
|
||||||
}
|
}
|
||||||
@ -1476,6 +1497,7 @@ rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
|
|||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* enum.one? [{ |obj| block }] -> true or false
|
* 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
|
* Passes each element of the collection to the given block. The method
|
||||||
* returns <code>true</code> if the block returns <code>true</code>
|
* returns <code>true</code> if the block returns <code>true</code>
|
||||||
@ -1483,17 +1505,22 @@ rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
|
|||||||
* <code>true</code> only if exactly one of the collection members is
|
* <code>true</code> only if exactly one of the collection members is
|
||||||
* true.
|
* 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 } #=> 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? { |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, 99 ].one? #=> false
|
||||||
* [ nil, true, false ].one? #=> true
|
* [ nil, true, false ].one? #=> true
|
||||||
|
* [ nil, true, 99 ].one?(Integer) #=> true
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static VALUE
|
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_ENUM_NEW(Qundef);
|
||||||
VALUE result;
|
VALUE result;
|
||||||
|
|
||||||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
|
||||||
@ -1514,23 +1541,29 @@ DEFINE_ENUMFUNCS(none)
|
|||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* enum.none? [{ |obj| block }] -> true or false
|
* 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
|
* Passes each element of the collection to the given block. The method
|
||||||
* returns <code>true</code> if the block never returns <code>true</code>
|
* 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
|
* 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.
|
* <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 == 5 } #=> true
|
||||||
* %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
|
* %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
|
||||||
|
* %w{ant bear cat}.none?(/d/) #=> true
|
||||||
|
* [1, 3.14, 42].none?(Float) #=> false
|
||||||
* [].none? #=> true
|
* [].none? #=> true
|
||||||
* [nil].none? #=> true
|
* [nil].none? #=> true
|
||||||
* [nil, false].none? #=> true
|
* [nil, false].none? #=> true
|
||||||
* [nil, false, true].none? #=> false
|
* [nil, false, true].none? #=> false
|
||||||
*/
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
enum_none(VALUE obj)
|
enum_none(int argc, VALUE *argv, VALUE obj)
|
||||||
{
|
{
|
||||||
struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
|
struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
|
||||||
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
|
||||||
return memo->v1;
|
return memo->v1;
|
||||||
}
|
}
|
||||||
@ -3969,10 +4002,10 @@ Init_Enumerable(void)
|
|||||||
rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
|
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, "group_by", enum_group_by, 0);
|
||||||
rb_define_method(rb_mEnumerable, "first", enum_first, -1);
|
rb_define_method(rb_mEnumerable, "first", enum_first, -1);
|
||||||
rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
|
rb_define_method(rb_mEnumerable, "all?", enum_all, -1);
|
||||||
rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
|
rb_define_method(rb_mEnumerable, "any?", enum_any, -1);
|
||||||
rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
|
rb_define_method(rb_mEnumerable, "one?", enum_one, -1);
|
||||||
rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
|
rb_define_method(rb_mEnumerable, "none?", enum_none, -1);
|
||||||
rb_define_method(rb_mEnumerable, "min", enum_min, -1);
|
rb_define_method(rb_mEnumerable, "min", enum_min, -1);
|
||||||
rb_define_method(rb_mEnumerable, "max", enum_max, -1);
|
rb_define_method(rb_mEnumerable, "max", enum_max, -1);
|
||||||
rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
|
rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
|
||||||
|
42
hash.c
42
hash.c
@ -2983,6 +2983,17 @@ any_p_i_fast(VALUE key, VALUE value, VALUE arg)
|
|||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
any_p_i_pattern(VALUE key, VALUE value, VALUE arg)
|
||||||
|
{
|
||||||
|
VALUE ret = rb_funcall(((VALUE *)arg)[1], idEqq, 1, rb_assoc_new(key, value));
|
||||||
|
if (RTEST(ret)) {
|
||||||
|
*(VALUE *)arg = Qtrue;
|
||||||
|
return ST_STOP;
|
||||||
|
}
|
||||||
|
return ST_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* hsh.any? [{ |(key, value)| block }] -> true or false
|
* hsh.any? [{ |(key, value)| block }] -> true or false
|
||||||
@ -2991,20 +3002,29 @@ any_p_i_fast(VALUE key, VALUE value, VALUE arg)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_hash_any_p(VALUE hash)
|
rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
|
||||||
{
|
{
|
||||||
VALUE ret = Qfalse;
|
VALUE args[2];
|
||||||
|
args[0] = Qfalse;
|
||||||
|
|
||||||
|
rb_check_arity(argc, 0, 1);
|
||||||
if (RHASH_EMPTY_P(hash)) return Qfalse;
|
if (RHASH_EMPTY_P(hash)) return Qfalse;
|
||||||
if (!rb_block_given_p()) {
|
if (argc) {
|
||||||
/* yields pairs, never false */
|
args[1] = argv[0];
|
||||||
return Qtrue;
|
|
||||||
|
rb_hash_foreach(hash, any_p_i_pattern, (VALUE)args);
|
||||||
}
|
}
|
||||||
if (rb_block_arity() > 1)
|
else {
|
||||||
rb_hash_foreach(hash, any_p_i_fast, (VALUE)&ret);
|
if (!rb_block_given_p()) {
|
||||||
else
|
/* yields pairs, never false */
|
||||||
rb_hash_foreach(hash, any_p_i, (VALUE)&ret);
|
return Qtrue;
|
||||||
return ret;
|
}
|
||||||
|
if (rb_block_arity() > 1)
|
||||||
|
rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
|
||||||
|
else
|
||||||
|
rb_hash_foreach(hash, any_p_i, (VALUE)args);
|
||||||
|
}
|
||||||
|
return args[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4663,7 +4683,7 @@ Init_Hash(void)
|
|||||||
rb_define_method(rb_cHash, "compare_by_identity", rb_hash_compare_by_id, 0);
|
rb_define_method(rb_cHash, "compare_by_identity", rb_hash_compare_by_id, 0);
|
||||||
rb_define_method(rb_cHash, "compare_by_identity?", rb_hash_compare_by_id_p, 0);
|
rb_define_method(rb_cHash, "compare_by_identity?", rb_hash_compare_by_id_p, 0);
|
||||||
|
|
||||||
rb_define_method(rb_cHash, "any?", rb_hash_any_p, 0);
|
rb_define_method(rb_cHash, "any?", rb_hash_any_p, -1);
|
||||||
rb_define_method(rb_cHash, "dig", rb_hash_dig, -1);
|
rb_define_method(rb_cHash, "dig", rb_hash_dig, -1);
|
||||||
|
|
||||||
rb_define_method(rb_cHash, "<=", rb_hash_le, 1);
|
rb_define_method(rb_cHash, "<=", rb_hash_le, 1);
|
||||||
|
@ -20,12 +20,19 @@ describe "Enumerable#any?" do
|
|||||||
{}.any? { nil }.should == false
|
{}.any? { nil }.should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises an ArgumentError when any arguments provided" do
|
it "raises an ArgumentError when more than 1 argument is provided" do
|
||||||
lambda { @enum.any?(Proc.new {}) }.should raise_error(ArgumentError)
|
lambda { @enum.any?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
lambda { @enum.any?(nil) }.should raise_error(ArgumentError)
|
lambda { [].any?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
lambda { @empty.any?(1) }.should raise_error(ArgumentError)
|
lambda { {}.any?(1, 2, 3) }.should raise_error(ArgumentError)
|
||||||
lambda { @enum1.any?(1) {} }.should raise_error(ArgumentError)
|
end
|
||||||
lambda { @enum2.any?(1, 2, 3) {} }.should raise_error(ArgumentError)
|
|
||||||
|
ruby_version_is ""..."2.5" do
|
||||||
|
it "raises an ArgumentError when any arguments provided" do
|
||||||
|
lambda { @enum.any?(Proc.new {}) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @enum.any?(nil) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @empty.any?(1) }.should raise_error(ArgumentError)
|
||||||
|
lambda { @enum1.any?(1) {} }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not hide exceptions out of #each" do
|
it "does not hide exceptions out of #each" do
|
||||||
@ -138,4 +145,81 @@ describe "Enumerable#any?" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.5" do
|
||||||
|
describe 'when given a pattern argument' do
|
||||||
|
class EnumerableSpecs::Pattern
|
||||||
|
attr_reader :yielded
|
||||||
|
def initialize(&block)
|
||||||
|
@block = block
|
||||||
|
@yielded = []
|
||||||
|
end
|
||||||
|
def ===(*args)
|
||||||
|
@yielded << args
|
||||||
|
@block.call(*args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls `===` on the pattern the return value " do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
|
||||||
|
@enum1.any?(pattern).should == true
|
||||||
|
pattern.yielded.should == [[0], [1], [2]]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ignores block" do
|
||||||
|
@enum2.any?(NilClass) { raise }.should == true
|
||||||
|
[1, 2, nil].any?(NilClass) { raise }.should == true
|
||||||
|
{a: 1}.any?(Array) { raise }.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "always returns false on empty enumeration" do
|
||||||
|
@empty.any?(Integer).should == false
|
||||||
|
[].any?(Integer).should == false
|
||||||
|
{}.any?(NilClass).should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of #each" do
|
||||||
|
lambda {
|
||||||
|
EnumerableSpecs::ThrowingEach.new.any?(Integer)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if the pattern ever returns a truthy value" do
|
||||||
|
@enum2.any?(NilClass).should == true
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| 42 }
|
||||||
|
@enum.any?(pattern).should == true
|
||||||
|
|
||||||
|
[1, 42, 3].any?(pattern).should == true
|
||||||
|
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] }
|
||||||
|
{a: 1, b: 2}.any?(pattern).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "any? should return false if the block never returns other than false or nil" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { |x| nil }
|
||||||
|
@enum1.any?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[0], [1], [2], [-1]]
|
||||||
|
|
||||||
|
[1, 2, 3].any?(pattern).should == false
|
||||||
|
{a: 1}.any?(pattern).should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not hide exceptions out of the block" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
|
||||||
|
lambda {
|
||||||
|
@enum.any?(pattern)
|
||||||
|
}.should raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls the pattern with gathered array when yielded with multiple arguments" do
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { false }
|
||||||
|
EnumerableSpecs::YieldsMixed2.new.any?(pattern).should == false
|
||||||
|
pattern.yielded.should == EnumerableSpecs::YieldsMixed2.gathered_yields.map { |x| [x] }
|
||||||
|
|
||||||
|
pattern = EnumerableSpecs::Pattern.new { false }
|
||||||
|
{a: 1, b: 2}.any?(pattern).should == false
|
||||||
|
pattern.yielded.should == [[[:a, 1]], [[:b, 2]]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -310,6 +310,8 @@ class TestEnumerable < Test::Unit::TestCase
|
|||||||
assert_equal(false, [true, true, false].all?)
|
assert_equal(false, [true, true, false].all?)
|
||||||
assert_equal(true, [].all?)
|
assert_equal(true, [].all?)
|
||||||
assert_equal(true, @empty.all?)
|
assert_equal(true, @empty.all?)
|
||||||
|
assert_equal(true, @obj.all?(Fixnum))
|
||||||
|
assert_equal(false, @obj.all?(1..2))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_any
|
def test_any
|
||||||
@ -319,27 +321,43 @@ class TestEnumerable < Test::Unit::TestCase
|
|||||||
assert_equal(false, [false, false, false].any?)
|
assert_equal(false, [false, false, false].any?)
|
||||||
assert_equal(false, [].any?)
|
assert_equal(false, [].any?)
|
||||||
assert_equal(false, @empty.any?)
|
assert_equal(false, @empty.any?)
|
||||||
|
assert_equal(true, @obj.any?(1..2))
|
||||||
|
assert_equal(false, @obj.any?(Float))
|
||||||
|
assert_equal(false, [1, 42].any?(Float))
|
||||||
|
assert_equal(true, [1, 4.2].any?(Float))
|
||||||
|
assert_equal(false, {a: 1, b: 2}.any?(->(kv) { kv == [:foo, 42] }))
|
||||||
|
assert_equal(true, {a: 1, b: 2}.any?(->(kv) { kv == [:b, 2] }))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_one
|
def test_one
|
||||||
assert(@obj.one? {|x| x == 3 })
|
assert(@obj.one? {|x| x == 3 })
|
||||||
assert(!(@obj.one? {|x| x == 1 }))
|
assert(!(@obj.one? {|x| x == 1 }))
|
||||||
assert(!(@obj.one? {|x| x == 4 }))
|
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? {|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, 99 ].one?))
|
||||||
assert([ nil, true, false ].one?)
|
assert([ nil, true, false ].one?)
|
||||||
assert(![].one?)
|
assert(![].one?)
|
||||||
assert(!@empty.one?)
|
assert(!@empty.one?)
|
||||||
|
assert([ nil, true, 99 ].one?(Integer))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_none
|
def test_none
|
||||||
assert(@obj.none? {|x| x == 4 })
|
assert(@obj.none? {|x| x == 4 })
|
||||||
assert(!(@obj.none? {|x| x == 1 }))
|
assert(!(@obj.none? {|x| x == 1 }))
|
||||||
assert(!(@obj.none? {|x| x == 3 }))
|
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 == 5})
|
||||||
assert(!(%w{ant bear cat}.none? {|word| word.length >= 4}))
|
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([].none?)
|
||||||
assert([nil].none?)
|
assert([nil].none?)
|
||||||
assert([nil,false].none?)
|
assert([nil,false].none?)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user