[前][次][番号順一覧][スレッド一覧]

ruby-changes:58634

From: Kazuki <ko1@a...>
Date: Fri, 8 Nov 2019 11:38:58 +0900 (JST)
Subject: [ruby-changes:58634] d4da74ea78 (master): Define Struct#deconstruct_keys

https://git.ruby-lang.org/ruby.git/commit/?id=d4da74ea78

From d4da74ea786da7906fdb85e593593a9c6c11fe96 Mon Sep 17 00:00:00 2001
From: Kazuki Tsujimoto <kazuki@c...>
Date: Fri, 8 Nov 2019 11:37:07 +0900
Subject: Define Struct#deconstruct_keys


diff --git a/struct.c b/struct.c
index 273c719..f4ae094 100644
--- a/struct.c
+++ b/struct.c
@@ -944,6 +944,33 @@ rb_struct_to_h(VALUE s) https://github.com/ruby/ruby/blob/trunk/struct.c#L944
     return h;
 }
 
+static VALUE
+rb_struct_deconstruct_keys(VALUE s, VALUE keys)
+{
+    VALUE h;
+    long i;
+
+    if (NIL_P(keys)) {
+        return rb_struct_to_h(s);
+    }
+    if (UNLIKELY(!RB_TYPE_P(keys, T_ARRAY))) {
+	rb_raise(rb_eTypeError,
+                 "wrong argument type %"PRIsVALUE" (expected Array or nil)",
+                 rb_obj_class(keys));
+
+    }
+    h = rb_hash_new_with_size(RARRAY_LEN(keys));
+    for (i=0; i<RARRAY_LEN(keys); i++) {
+        VALUE key = RARRAY_AREF(keys, i);
+        int i = rb_struct_pos(s, &key);
+        if (i < 0) {
+            return rb_hash_new_with_size(0);
+        }
+        rb_hash_aset(h, key, RSTRUCT_GET(s, i));
+    }
+    return h;
+}
+
 /* :nodoc: */
 VALUE
 rb_struct_init_copy(VALUE copy, VALUE s)
@@ -1357,6 +1384,7 @@ InitVM_Struct(void) https://github.com/ruby/ruby/blob/trunk/struct.c#L1384
     rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
 
     rb_define_method(rb_cStruct, "deconstruct", rb_struct_to_a, 0);
+    rb_define_method(rb_cStruct, "deconstruct_keys", rb_struct_deconstruct_keys, 1);
 }
 
 #undef rb_intern
diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb
index 0338f90..9af091a 100644
--- a/test/ruby/test_pattern_matching.rb
+++ b/test/ruby/test_pattern_matching.rb
@@ -1230,6 +1230,30 @@ END https://github.com/ruby/ruby/blob/trunk/test/ruby/test_pattern_matching.rb#L1230
         true
       end
     end
+
+    s = Struct.new(:a, :b, keyword_init: true)
+    assert_block do
+      case s[a: 0, b: 1]
+      in **r
+        r == {a: 0, b: 1}
+      end
+    end
+    assert_block do
+      s = Struct.new(:a, :b, keyword_init: true)
+      case s[a: 0, b: 1]
+      in a:, b:
+        a == 0 && b == 1
+      end
+    end
+    assert_block do
+      s = Struct.new(:a, :b, keyword_init: true)
+      case s[a: 0, b: 1]
+      in a:, c:
+        flunk
+      in b:
+        b == 1
+      end
+    end
   end
 
   ################################################################
diff --git a/test/ruby/test_struct.rb b/test/ruby/test_struct.rb
index 22a6ce8..06a8a1b 100644
--- a/test/ruby/test_struct.rb
+++ b/test/ruby/test_struct.rb
@@ -431,6 +431,18 @@ module TestStruct https://github.com/ruby/ruby/blob/trunk/test/ruby/test_struct.rb#L431
     }
   end
 
+  def test_deconstruct_keys
+    klass = @Struct.new(:a, :b)
+    o = klass.new(1, 2)
+    assert_equal({a: 1, b: 2}, o.deconstruct_keys(nil))
+    assert_equal({a: 1, b: 2}, o.deconstruct_keys([:b, :a]))
+    assert_equal({a: 1}, o.deconstruct_keys([:a]))
+    assert_equal({}, o.deconstruct_keys([:a, :c]))
+    assert_raise(TypeError) {
+      o.deconstruct_keys(0)
+    }
+  end
+
   class TopStruct < Test::Unit::TestCase
     include TestStruct
 
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]