Ruby Integer (), Array () and others - what are they? Where are they from?

I met transformations of the form Array (value), String (value) and Integer (value). It seems to me that this is just syntactic sugar for calling the corresponding methods value.to_a, value.to_s or value.to_i.

So, I am wondering:

  • Where / how are they defined? I can not find them in Object, Module, Class, etc.
  • Are there common scenarios for which it is preferable to use them, rather than the corresponding / main method to_X?
  • Can they be used in typical coercion? That is, can I do something in the lines

    [Integer, String, Array].each {|klass| klass.do_generic_coercion(foo) } 

? (... and no, I really don't want to do this, I know the type I want, but I try to avoid the case statement.)

+4
source share
4 answers

This is a good and difficult question. Let me answer in three parts.

First part

To find a definition, it is important to understand that the name of the method is "Array", etc., which can be quite inconsistent, since methods usually have lowercase letters ...

 irb> method(:Array) => #<Method: Object(Kernel)#Array> 

This tells you that they are defined in the kernel and thus are available everywhere without requiring an explicit prefix.

The second part

Array() , String() , ... are conversion methods. Calling obj.to_a will return an array, but raise a NoMethodError if obj does not respond_to? :to_a respond_to? :to_a . Therefore, the typical case is when you prefer to use Array() , String() instead of to_a or to_s , when you are not sure that the object is responding to this conversion method.

String(obj) will return nil if obj does not respond_to? :to_s respond_to? :to_s . String (obj) will also verify that the result of to_s is actually a string; it should be, but maybe a too creative programmer decided to return something else?

Most other conversion methods work the same, but Array(obj) is different. It will return [obj] if obj does not respond_to? :to_a respond_to? :to_a . It actually calls to_ary (this is an implicit conversion operation, and to_a is explicit).

There is another important way to convert objects to 1.9 (and future 1.8.8): Array.try_convert(obj) . Does this return nil if obj does not respond_to? :to_ary respond_to? :to_ary . He will not call to_a . Although they are longer for input, you can use them when writing very general code that can accept different types of objects, and you want, for example, to avoid converting the hash into an array, for example (since Hash has a to_a method but not to_ary ). When your method requires an object like an array, and you are ready to do an explicit conversion, then obj.to_a will be fine. A typical use of Array(obj) will be in a method that takes either one obj for an action or a list of objects (although this is usually written as [*obj] ).

the last part

Hopefully the answers to the first two parts will give you the final answer ...

You can use:

 [Integer, String, Array].each {|klass| klass.try_convert(foo) } 

or

 [:Integer, :String, :Array].each{|method| send(method, obj)} 
+9
source

Good question! Let's see if we can figure it out.

 Ross-Harveys-MacBook-Pro:ruby-1.9.1-p376 ross$ irb irb(main):001:0> Object.ancestors => [Object, Kernel] irb(main):002:0> Kernel.ancestors => [Kernel] irb(main):003:0> Kernel.class => Module irb(main):004:0> Kernel.public_methods.include? "Array" => true 

So, it looks like these are methods in the kernel module that are mixed with Object, so they are available without specifying the recipient. We could also look into the C implementation, in object.c:

 VALUE rb_Array(VALUE val) { VALUE tmp = rb_check_array_type(val); if (NIL_P(tmp)) { tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_a"); if (NIL_P(tmp)) { return rb_ary_new3(1, val); } } return tmp; } 

On the one hand, it’s easy to conclude that the default .to_a is deprecated, so it appears that Array(x) is a canonical conversion method. Apparently, it does nothing if an array is given, calls .to_a if it is present, and if it just does not transfer its argument to the array.

Regarding whether to_a deprecated ... well, I said "default":

 Ross-Harveys-MacBook-Pro:puppet_sd ross$ irb irb(main):001:0> class X; X; end.new.to_a (irb):1: warning: default `to_a' will be obsolete 
+8
source

They are defined in the Ruby kernel module, for example:

  Array (), Complex (), Float (), Integer (), Rational (), Stirng (), etc. 

I found these method references in Dave Thomas Pickaxe's book Programming Ruby 1.9, "p. 555.

For example: Array (arg) converts arg as an array, and then copied from the book: "Returns arg as an array. First it tries to call rg.to_ary, and then arg.to_a. If both fail, it creates one array of elements containing arg (or empty array if arg is nil) ". ex.

  Array (1..5) # => [1, 2, 3, 4, 5] 
0
source

From what I understand, a simple version looks like this:

  • object.to_a trying to convert an "object" into an array using a class member function.
  • Array(object) trying to create a new array using the "object".

I can override what .to_a means for a given class (this is just another member). The call to Array(...) is defined in the kernel, so it behaves the same for any class. I usually use Array(...) style type conversions when I don’t know in advance what type of object will be passed. This is best when handling cases where the object does not know how to convert itself to an array or can 'convert to an array. If the object to be transformed is the result of a long or complex expression, using the Array(...) style often becomes clearer. I save the .to_a form for instances when I know the class of the object and what exactly to expect from the output of .to_a (mostly instances when I wrote or modified the member function .to_a ).

0
source

All Articles