Revision: 5258 http://trac.macosforge.org/projects/ruby/changeset/5258 Author: watson1978@gmail.com Date: 2011-03-06 22:11:34 -0800 (Sun, 06 Mar 2011) Log Message: ----------- Implements the Hash#keep_if. Test Script: {{{ require 'test/unit/assertions.rb' include Test::Unit::Assertions hash = { "Alice" => 50, "Bob" => 60, "Carol" => 90, "David" => 40 } assert_equal({"Alice"=>50, "Bob"=>60, "Carol"=>90}, hash.keep_if {|key, val| val >= 50 } ) puts :ok }}} Modified Paths: -------------- MacRuby/trunk/hash.c MacRuby/trunk/spec/frozen/tags/macruby/core/hash/keep_if_tags.txt Modified: MacRuby/trunk/hash.c =================================================================== --- MacRuby/trunk/hash.c 2011-03-06 11:55:02 UTC (rev 5257) +++ MacRuby/trunk/hash.c 2011-03-07 06:11:34 UTC (rev 5258) @@ -872,6 +872,40 @@ /* * call-seq: + * hsh.keep_if {| key, value | block } -> hsh + * hsh.keep_if -> an_enumerator + * + * Deletes every key-value pair from <i>hsh</i> for which <i>block</i> + * evaluates to false. + * + * If no block is given, an enumerator is returned instead. + * + */ + +static int +keep_if_i(VALUE key, VALUE value, VALUE hash) +{ + if (key != Qundef) { + const bool ok = RTEST(rb_yield_values(2, key, value)); + ST_STOP_IF_BROKEN(); + if (!ok) { + return ST_DELETE; + } + } + return ST_CONTINUE; +} + +VALUE +rhash_keep_if(VALUE hash, SEL sel) +{ + RETURN_ENUMERATOR(hash, 0, 0); + rhash_modify(hash); + rhash_foreach(hash, keep_if_i, hash); + return hash; +} + +/* + * call-seq: * hsh.clear -> hsh * * Removes all key-value pairs from <i>hsh</i>. @@ -1123,12 +1157,8 @@ { VALUE ary = rb_ary_new(); rhash_foreach(hash, to_a_i, ary); - if (OBJ_TAINTED(hash)) { - OBJ_TAINT(ary); - } - if (OBJ_UNTRUSTED(hash)) { - OBJ_UNTRUST(ary); - } + OBJ_INFECT(ary, hash); + return ary; } @@ -1834,6 +1864,7 @@ rb_objc_define_method(rb_cRubyHash, "shift", rhash_shift, 0); rb_objc_define_method(rb_cRubyHash, "delete", rhash_delete, 1); rb_objc_define_method(rb_cRubyHash, "delete_if", rhash_delete_if, 0); + rb_objc_define_method(rb_cRubyHash, "keep_if", rhash_keep_if, 0); rb_objc_define_method(rb_cRubyHash, "select", rhash_select, 0); rb_objc_define_method(rb_cRubyHash, "reject", rhash_reject, 0); rb_objc_define_method(rb_cRubyHash, "reject!", rhash_reject_bang, 0); Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/hash/keep_if_tags.txt =================================================================== --- MacRuby/trunk/spec/frozen/tags/macruby/core/hash/keep_if_tags.txt 2011-03-06 11:55:02 UTC (rev 5257) +++ MacRuby/trunk/spec/frozen/tags/macruby/core/hash/keep_if_tags.txt 2011-03-07 06:11:34 UTC (rev 5258) @@ -1,6 +0,0 @@ -fails:Hash#keep_if yields two arguments: key and value -fails:Hash#keep_if keeps every entry for which block is true and returns self -fails:Hash#keep_if returns self even if unmodified -fails:Hash#keep_if raises an RuntimeError if called on a frozen instance -fails:Hash#keep_if returns an Enumerator if called on a non-empty hash without a block -fails:Hash#keep_if returns an Enumerator if called on an empty hash without a block