Determining type of an object in ruby
The proper way to determine the "type" of an object, which is a wobbly term in the Ruby world, is to call object.class
.
Since classes can inherit from other classes, if you want to determine if an object is "of a particular type" you might call object.is_a?(ClassName)
to see if object
is of type ClassName
or derived from it.
Normally type checking is not done in Ruby, but instead objects are assessed based on their ability to respond to particular methods, commonly called "Duck typing". In other words, if it responds to the methods you want, there's no reason to be particular about the type.
For example, object.is_a?(String)
is too rigid since another class might implement methods that convert it into a string, or make it behave identically to how String behaves. object.respond_to?(:to_s)
would be a better way to test that the object in question does what you want.
Function to find object type in Ruby
The assumption you've made is that if the value returned by a mathematical operation is an integer, the value's class will be Fixnum. That's not correct.
Take a look:
a = 5
puts a.class
# => Fixnum
b = 5.0
puts b.class
# => Float
Mathematically speaking, 5 and 5.0 are the same number and that number is an integer. But 5 and 5.0 in Ruby (like many other programming languages) are not the same. One is a fixed-point value (ergo Fixnum) and the other is a floating-point value (Float). A Fixnum can represent integers only, but a Float can represent both integers and fractions (but, it behooves me to mention, not all fractions).
In Ruby, when you do a mathematical operation with two Fixnums, a Fixnum is returned:
a = 4
puts a.class # => Fixnum
x = a ** 2
puts x # => 16
puts x.class # => Fixnum
However, if either number is a Float, a Float is returned:
a = 4
x = a ** 2.0
puts x # => 16.0
puts x.class # => Float
b = 4.0
puts b.class # => Float
y = b ** 2
puts y # => 16.0
puts y.class # => Float
y = b ** 2.0
puts y # => 16.0
puts y.class # => Float
You asked how to "find the type of an object," and the answer to that question is to use the Object#class
method, as above. But as you can see, "Is the object a Fixnum?" and "Is the object an integer?" are two different questions.
If you want to know if a number in Ruby is an integer even if it's a Float, refer to the excellent answers to this question: Checking if a Float is equivalent to an integer value in Ruby
Checking variable type in Ruby
I think you are looking for Object#class
. Here:
element = {}
element.class
# => Hash
a = []
a.class
# => Array
This will make your switch case as follows:
case element
when String
# do something
when Fixnum
# do something
when Hash
# do something
when Array
# do something
end
Note:
As mentioned by @ndn in comments below, case
statement should not have .class
in it (which I had initially in my answer). You can find the explanation here.
Is there a Ruby equivalent for the typeof reserved word in C#?
In addition to checking Object#class (the instance method class on the Object aka Base class), you could
s.is_a? Thing
this will check to see if s has Thing anywhere in its ancestry.
Checking the type of a method parameter
Use the Kernel#Integer method to convert the input before using it. It will raise an ArgumentError
when the input could not be converted to an integer in any reasonable fashion.
def my_method(number)
number = Integer(number)
# do something with number, which is now guaranteed to be an integer
end
I recommend Avdi Grimm's new book Confident Ruby for more insight into this.
Discovering Ruby object members?
"foo".methods
See:
http://ruby-doc.org/core/classes/Object.html
http://ruby-doc.org/core/classes/Class.html
http://ruby-doc.org/core/classes/Module.html
Mimic another Ruby class so the object passes the === type check
This is a hackish solution that I warned against in my question:
Fixnum === page #=> false
Numeric.extend Module.new {
def ===(obj)
obj.instance_of?(PageNumber) or super
end
}
Fixnum === page #=> true
It solves the problem but raises a question is it safe to do? I can't think of any drawbacks of this method from the top of my mind but since we're messing with a very important method here it might not be something we'd want to do.
Ruby - determining method origins?
Object#method
returns a Method
object giving meta-data about a given method. For example:
> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"
In Ruby 1.8.7 and later, you can use Method#owner
to determine the class or module that defined the method.
To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:
obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
To which level returns a return inside a Proc Object in Ruby?
As a general rule, return
always returns from the closest lexically enclosing method definition expression.
In this case, the closest lexically enclosing method definition expression is def a
, therefore, return
returns from a
.
It does not actually matter that the return
is inside a block in this case. The general rule is, well, general, so it applies regardless of where the return
appears.
If we look more specifically at blocks, though, we can see that it still makes sense: in blocks, local variables are captured lexically, self
is captured lexically, so it makes sense that return
also behaves lexically. It is a general property of blocks that if you want to understand what is going on in a block, you only need to look lexically outwards.
And if we get even more specific, first going from the general rule to blocks, and now from blocks to Proc
s, the behavior still makes sense: a Proc
is essentially a reified block, so it makes sense for a Proc
to behave like a block.
There are some exceptions, though, to the general rule, and one important one are lambdas. Talking about lambdas in Ruby is always a little bit weird because lambdas are Proc
s but they behave differently from Proc
s. IMO, lambdas should have a separate class alongside Proc
s. Since lambdas are Proc
s, it makes it weird to talk about the differences between lambdas and Proc
s which are not lambdas (which don't have a standardized name and thus are confusingly also called Proc
s).
The behavior of a lambda differs from the behavior of a non-lambda Proc
in two ways, one of which is relevant to your question:
- Parameter binding in non-lambda
Proc
s has the same semantics as parameter binding in blocks, whereas parameter binding in lambdas has the same semantics as parameter binding in message sends / method invocations. - In non-lambda
Proc
s,return
returns from the closest lexically enclosing method definition expression, just like in blocks, whereas in lambdas,return
returns from the lambda itself, just likereturn
in methods.
So, in both of these aspects, non-lambda Proc
s behave like blocks and lambdas behave like methods. I memorize it like this: "Proc
" rhymes with "block" and both "lambda" and "method" are Greek.
As you probably know, there are some methods which also alter the behavior of blocks that are passed to them. E.g. instance_eval
and instance_exec
change the value of self
, and define_method
actually does change the behavior of return
.
But since you didn't ask about blocks in general, and also didn't ask about lambdas specifically, and there are no reflective methods in your question, the general rules still applies to non-lambda Proc
s like the one shown in your question: return
returns from the closest lexically enclosing method definition expression.
Related Topics
Marshal (Ruby) Pipes: Sending Serialized Object to Child Processes
How to Print a Line Number in Ruby
How to Convert a Formatted String into Plain Text
Perfect Way to Write a Gsub for a Regex Match
Regex to Remove the Webpage Part of a Url in Ruby
Ruby, No Implicit Conversion of Symbol into Integer
How to Set Up These Crud Controller Actions for Has_Many_Polymorphs and an Error
Does Will Pagination Work with Forms Which Have Method="Post"
Pow Not Loading Gem Properly While Rails S Works
How to Add "Access-Control-Allow-Origin" Headers to API Response in Ruby
How to Share Image and Description Using Social_Share_Button in Rails
Accessing Values Through Ajax Calls and Partials in Rails
How to Install Nokogiri on MAC Os Sierra 10.12
Devise Password Reset from Rails Console