Feature #12719 ยป struct_merge.patch
ChangeLog | ||
---|---|---|
1 |
Fri Sep 2 17:27:31 2016 Matthew Mongeau <halogenandtoast@gmail.com> |
|
2 | ||
3 |
* struct.c (rb_struct_update): Add Struct#merge and Struct#merge! |
|
4 |
for updating structs |
|
5 | ||
1 | 6 |
Fri Sep 2 16:06:59 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> |
2 | 7 | |
3 | 8 |
* internal.h (MEMO_V1_SET, MEMO_V2_SET): fix typos. use the macro |
struct.c | ||
---|---|---|
894 | 894 |
return RSTRUCT_GET(s, i); |
895 | 895 |
} |
896 | 896 | |
897 |
static int |
|
898 |
value_update(VALUE key, VALUE value, VALUE s) |
|
899 |
{ |
|
900 |
rb_struct_aset(s, key, value); |
|
901 |
return ST_CONTINUE; |
|
902 |
} |
|
903 | ||
904 |
/* |
|
905 |
* call-seq: |
|
906 |
* struct.merge!(hash) -> struct |
|
907 |
* |
|
908 |
* Updates the values of the struct using the keys and values of the hash |
|
909 |
* |
|
910 |
* Point = Struct.new(:x, :y) |
|
911 |
* hash = { "x" => 5 } |
|
912 |
* point = Point.new(1, 2) |
|
913 |
* point.merge!(hash) |
|
914 |
* |
|
915 |
* point.x #=> 5 |
|
916 |
*/ |
|
917 | ||
918 |
VALUE |
|
919 |
rb_struct_update(VALUE self, VALUE hash) |
|
920 |
{ |
|
921 |
VALUE converted_hash = rb_convert_type(hash, T_HASH, "Hash", "to_hash"); |
|
922 | ||
923 |
rb_hash_foreach(converted_hash, value_update, self); |
|
924 | ||
925 |
return self; |
|
926 |
} |
|
927 | ||
928 |
/* |
|
929 |
* call-seq: |
|
930 |
* struct.merge(hash) -> new_struct |
|
931 |
* |
|
932 |
* Returns a new struct with updated values using the keys and values of |
|
933 |
* the hash |
|
934 |
* |
|
935 |
* Point = Struct.new(:x, :y) |
|
936 |
* p = Point.new(1, 2) |
|
937 |
* p2 = p.merge(y: 20) |
|
938 |
* |
|
939 |
* p.y #=> 2 |
|
940 |
* p2.y #=> 20 |
|
941 |
*/ |
|
942 | ||
943 |
VALUE |
|
944 |
rb_struct_merge(VALUE self, VALUE hash) |
|
945 |
{ |
|
946 |
VALUE dup = rb_obj_dup(self); |
|
947 |
return rb_struct_update(dup, hash); |
|
948 |
} |
|
949 | ||
897 | 950 |
/* |
898 | 951 |
* call-seq: |
899 | 952 |
* struct[member] = obj -> obj |
... | ... | |
1215 | 1268 | |
1216 | 1269 |
rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0); |
1217 | 1270 |
rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1); |
1271 | ||
1272 |
rb_define_method(rb_cStruct, "merge", rb_struct_merge, 1); |
|
1273 |
rb_define_method(rb_cStruct, "merge!", rb_struct_update, 1); |
|
1218 | 1274 |
} |
1219 | 1275 | |
1220 | 1276 |
#undef rb_intern |
test/ruby/test_struct.rb | ||
---|---|---|
367 | 367 |
assert_nil(o.dig(:b, 0)) |
368 | 368 |
end |
369 | 369 | |
370 |
def test_merge! |
|
371 |
klass = @Struct.new(:a, :b) |
|
372 |
o = klass.new(1, 2) |
|
373 |
o.merge!(a: 10) |
|
374 |
assert_equal(o.a, 10) |
|
375 |
assert_equal(o.b, 2) |
|
376 | ||
377 |
o.merge!("b" => 5) |
|
378 |
assert_equal(o.b, 5) |
|
379 | ||
380 |
assert_raise(TypeError) { |
|
381 |
o.merge(0) |
|
382 |
} |
|
383 |
end |
|
384 | ||
385 |
def test_merge |
|
386 |
klass = @Struct.new(:a, :b) |
|
387 |
o = klass.new(1, 2) |
|
388 |
p = o.merge(a: 10) |
|
389 |
assert_equal(p.a, 10) |
|
390 |
assert_equal(p.b, 2) |
|
391 |
assert_equal(o.a, 1) |
|
392 |
assert_equal(o.b, 2) |
|
393 | ||
394 |
assert_raise(TypeError) { |
|
395 |
o.merge(0) |
|
396 |
} |
|
397 |
end |
|
398 | ||
370 | 399 |
def test_new_dupilicate |
371 | 400 |
bug12291 = '[ruby-core:74971] [Bug #12291]' |
372 | 401 |
assert_raise_with_message(ArgumentError, /duplicate member/, bug12291) { |