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

ruby-changes:60881

From: Burdette <ko1@a...>
Date: Thu, 23 Apr 2020 17:46:51 +0900 (JST)
Subject: [ruby-changes:60881] f563f3c5ef (master): RDoc enhancements for Hash[].

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

From f563f3c5ef517b62f1a95ab03286335e4fe72314 Mon Sep 17 00:00:00 2001
From: Burdette Lamar <BurdetteLamar@Y...>
Date: Thu, 23 Apr 2020 03:46:20 -0500
Subject: RDoc enhancements for Hash[].


diff --git a/doc/implicit_conversion.rdoc b/doc/implicit_conversion.rdoc
new file mode 100644
index 0000000..fae5973
--- /dev/null
+++ b/doc/implicit_conversion.rdoc
@@ -0,0 +1,198 @@ https://github.com/ruby/ruby/blob/trunk/doc/implicit_conversion.rdoc#L1
+== Implicit Conversions
+
+Some Ruby methods accept one or more objects
+that can be either:
+* <i>Of a given class</i>, and so accepted as is.
+* <i>Implicitly convertible to that class</i>, in which case
+  the called method converts the object.
+
+For each of the relevant classes, the conversion is done by calling
+a specific conversion method:
+
+* Array: +to_ary+
+* Hash: +to_hash+
+* Integer: +to_int+
+* String: +to_str+
+
+=== Array-Convertible Objects
+
+An <i>Array-convertible object</i> is an object that:
+* Has instance method +to_ary+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(Array)</tt> returns +true+.
+
+The examples in this section use method <tt>Array#replace</tt>,
+which accepts an Array-convertible argument.
+
+This class is Array-convertible:
+
+    class ArrayConvertible
+      def to_ary
+        [:foo, 'bar', baz = 2]
+      end
+    end
+    a = []
+    a.replace(ArrayConvertible.new) # => [:foo, "bar", 2]
+
+This class is not Array-convertible (no +to_ary+ method):
+
+    class NotArrayConvertible; end
+    a = []
+    # Raises TypeError (no implicit conversion of NotArrayConvertible into Array)
+    a.replace(NotArrayConvertible.new)
+
+This class is not Array-convertible (method +to_ary+ takes arguments):
+
+    class NotArrayConvertible
+      def to_ary(x)
+        [:foo, 'bar', baz = 2]
+      end
+    end
+    a = []
+    # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+    a.replace(NotArrayConvertible.new)
+
+This class is not Array-convertible (method +to_ary+ returns non-Array):
+
+    class NotArrayConvertible
+      def to_ary
+        :foo
+      end
+    end
+    a = []
+    # Raises TypeError (can't convert NotArrayConvertible to Array (NotArrayConvertible#to_ary gives Symbol))
+    a.replace(NotArrayConvertible.new)
+
+=== Hash-Convertible Objects
+
+A <i>Hash-convertible object</i> is an object that:
+* Has instance method +to_hash+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(Hash)</tt> returns +true+.
+
+The examples in this section use method <tt>Hash#merge</tt>,
+which accepts a Hash-convertible argument.
+
+This class is Hash-convertible:
+
+    class HashConvertible
+      def to_hash
+        {foo: 0, bar: 1, baz: 2}
+      end
+    end
+    h = {}
+    h.merge(HashConvertible.new) # => {:foo=>0, :bar=>1, :baz=>2}
+
+This class is not Hash-convertible (no +to_hash+ method):
+
+    class NotHashConvertible; end
+    h = {}
+    # Raises TypeError (no implicit conversion of NotHashConvertible into Hash)
+    h.merge(NotHashConvertible.new)
+
+This class is not Hash-convertible (method +to_hash+ takes arguments):
+
+    class NotHashConvertible
+      def to_hash(x)
+        {foo: 0, bar: 1, baz: 2}
+      end
+    end
+    h = {}
+    # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+    h.merge(NotHashConvertible.new)
+
+This class is not Hash-convertible (method +to_hash+ returns non-Hash):
+
+    class NotHashConvertible
+      def to_hash
+        :foo
+      end
+    end
+    h = {}
+    # Raises TypeError (can't convert NotHashConvertible to Hash (ToHashReturnsNonHash#to_hash gives Symbol))
+    h.merge(NotHashConvertible.new)
+
+=== Integer-Convertible Objects
+
+An <i>Integer-convertible object</i> is an object that:
+* Has instance method +to_int+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(Integer)</tt> returns +true+.
+
+The examples in this section use method <tt>Array.new</tt>,
+which accepts an Integer-convertible argument.
+
+This user-defined class is Integer-convertible:
+
+    class IntegerConvertible
+      def to_int
+        3
+      end
+    end
+    a = Array.new(IntegerConvertible.new).size
+    a # => 3
+
+This class is not Integer-convertible (method +to_int+ takes arguments):
+
+    class NotIntegerConvertible
+      def to_int(x)
+        3
+      end
+    end
+    # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+    Array.new(NotIntegerConvertible.new)
+
+This class is not Integer-convertible (method +to_int+ returns non-Integer):
+
+    class NotIntegerConvertible
+      def to_int
+        :foo
+      end
+    end
+    # Raises TypeError (can't convert NotIntegerConvertible to Integer (NotIntegerConvertible#to_int gives Symbol))
+    Array.new(NotIntegerConvertible.new)
+
+=== String-Convertible Objects
+
+A <i>String-convertible object</i> is an object that:
+* Has instance method +to_str+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(String)</tt> returns +true+.
+
+The examples in this section use method <tt>String::new</tt>,
+which accepts a String-convertible argument.
+
+This class is String-convertible:
+
+    class StringConvertible
+      def to_str
+        'foo'
+      end
+    end
+    String.new(StringConvertible.new) # => "foo"
+
+This class is not String-convertible (no +to_str+ method):
+
+    class NotStringConvertible; end
+    # Raises TypeError (no implicit conversion of NotStringConvertible into String)
+    String.new(NotStringConvertible.new)
+
+This class is not String-convertible (method +to_str+ takes arguments):
+
+    class NotStringConvertible
+      def to_str(x)
+        'foo'
+      end
+    end
+    # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+    String.new(NotStringConvertible.new)
+
+This class is not String-convertible (method +to_str+ returns non-String):
+
+    class NotStringConvertible
+      def to_str
+        :foo
+      end
+    end
+    # Raises TypeError (can't convert NotStringConvertible to String (NotStringConvertible#to_str gives Symbol))
+    String.new(NotStringConvertible.new)
diff --git a/hash.c b/hash.c
index e0f827b..ab6dd3b 100644
--- a/hash.c
+++ b/hash.c
@@ -1810,22 +1810,74 @@ rb_hash_initialize(int argc, VALUE *argv, VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L1810
 
 /*
  *  call-seq:
- *     Hash[ key, value, ... ]         -> new_hash
- *     Hash[ [ [key, value], ... ] ]   -> new_hash
- *     Hash[ object ]                  -> new_hash
+ *    Hash[] -> new_empty_hash
+ *    Hash[ [*2_element_arrays] ] -> new_hash
+ *    Hash[*objects] -> new_hash
+ *    Hash[hash_convertible_object] -> new_hash
  *
- *  Creates a new hash populated with the given objects.
+ *  Returns a new \Hash object populated with the given objects, if any.
  *
- *  Similar to the literal <code>{ _key_ => _value_, ... }</code>. In the first
- *  form, keys and values occur in pairs, so there must be an even number of
- *  arguments.
+ *  The initial default value and default proc are set to <tt>nil</tt>
+ *  (see {Default Values}[#class-Hash-label-Default+Values]):
  *
- *  The second and third form take a single argument which is either an array
- *  of key-value pairs or an object convertible to a hash.
+ *    h = Hash[]
+ *    h # => {}
+ *    h.class # => Hash
+ *    h.default # => nil
+ *    h.default_proc # => nil
+ *
+ *  When argument <tt>[*2_element_arrays]</tt> is given,
+ *  each element of the outer array must be a 2-element array;
+ *  returns a new \Hash object wherein each 2-element array forms a key-value entry:
+ *
+ *    Hash[ [ [:foo, 0], [:bar, 1] ] ] # => {:foo=>0, :bar=>1}
+ *
+ *  When arguments <tt>*objects</tt> are given,
+ *  the argument count must be an even number;
+ *  returns a new \Hash object wherein each successive pair of arguments has become a key-value entry:
+ *
+ *    Hash[] # => {}
+ *    Hash[:foo, 0, :bar, 1] # => {:foo=>0, :bar=>1}
+ *
+ *  When argument <tt>hash_convertible_object</tt> is given,
+ *  the argument must be a
+ *  {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash-Convertible+Objects];
+ *  converts the object and returns the resulting \Hash object:
+ *
+ *    class Foo
+ *      def to_hash
+ *        {foo: 0, bar: 1}
+ *      end
+ *    end
+ *    Hash[Foo.new] # => {:foo=>0, :bar=>1}
+ *
+ *  ---
+ *
+ *  Raises an exception if the argument count is 1,
+ *  but the argument is not an array of 2-element arrays or a
+ *  {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash-Convertible+Objects]:
+ *
+ *    Hash[:foo] # Raises ArgumentError (odd number of arguments
+ *    Hash[ [ [:foo, 0, 1] ] ] # Raises ArgumentError (invalid number of elements (3 for 1..2))
+ *
+ *  Raises an exception if the argument count is odd and greater than 1:
+ *
+ *    Hash[0, 1, 2] # Raises ArgumentError (odd number of arguments for Hash)
+ *
+ *  Raises an exception if the argument is an array containing an element
+ *  that is not a 2-element array:
+ *
+ *    Hash[ [ :foo ] ] # Raises ArgumentError (wrong element type Symbol at 0 (expected array))
+ *
+ *  Raises an exception if the argument is an array containing an element
+ *  that is an array of size different from 2:
+ *
+ *    Hash[ [ [0, 1, 2] ] ] # Raises ArgumentError (invalid number of elements (3 for 1..2))
+ *
+ *  Raises an exception if any proposed key is not a valid key:
  *
- *     Hash["a", 100, "b", 200]             #=> {"a"=>100, "b"=>200}
- *     Hash[ [ ["a", 100], ["b", 200] ] ]   #=> {"a"=>100, "b"=>200}
- *     Hash["a" => 100, "b" => 200]         #=> {"a"=>100, "b"=>200}
+ *    Hash[:foo, 0, BasicObject.new, 1] # Raises NoMethodError (undefined method `hash' for #<BasicObject:>)
+ *    Hash[ [ [:foo, 0], [BasicObject.new, 1] ] ] # Raises NoMethodError (undefined  (... truncated)

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

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