views:

370

answers:

4

I was reading a text describing Ruby and it said the following:

Ruby is considered a “reflective” language because it’s possible for a Ruby program to analyze itself (in terms of its make-up), make adjustments to the way it works, and even overwrite its own code with other code.

I'm confused by this term 'reflective' - is this mainly talking about the way Ruby can look at a variable and figure out whether it's an Integer or a String (duck typing), e.g.:

x = 3
x = "three" # Ruby reassigns x to a String type
+2  A: 

No, it means that you can issue a ruby command to get information about, well, just about anything. For example, you can type the command File.methods() to get a listing of all methods belonging to the File module. You can do similar things with classes and objects -- listing methods, variables, etc.

Bryan Oakley
+9  A: 

To say Ruby is "reflective" means that you can, for instance, find out at runtime what methods a class has:

>> Array.methods
=> ["inspect", "private_class_method", "const_missing",
[ ... and many more ... ]

(You can do the same thing with an object of the class.)

Or you can find out what class a given object is...

>> arr = Array.new
=> []
>> arr.class
=> Array

And find out what it is within the class hierarchy...

>> arr.kind_of?
>> arr.kind_of? Array
=> true
>> arr.kind_of? String
=> false

In the quote where they say "it’s possible for a Ruby program to analyze itself" that's what they're talking about.

Other languages such as Java do that too, but with Ruby it's easier, more convenient, and more of an everyday part of using the language. Hence, Ruby is "reflective."

Ethan
+1  A: 

Class reopening is a good example of this. Here's a simple example:

class Integer
    def moxy
        if self.zero?
            self - 2
        elsif self.nonzero?
            self + 2          
        end      
    end  
end

puts 10.moxy

By reopening a standard Ruby class - Integer - and defining a new method within it called 'moxy', we can perform a newly defined operation directly on a number. In this case, I've defined this made up 'moxy' method to subtract 2 from the Integer if it's zero and add two if it's nonzero. This makes the moxy method available to all objects of class Integer in Ruby. (Here we use the 'self' keyword to get the content of the integer object).

As you can see, it's a very powerful feature of Ruby.

EDIT: Some commenters have questioned whether this is really reflection. In the English language the word reflection refers to looking in on your own thoughts. And that's certainly an important aspect of reflection in programming also - using Ruby methods like is_a, kind_of, instance_of to perform runtime self-inspection. But reflection also refers to the the ability of a program to modify its own behavior at runtime. Reopening classes is one of the key examples of this. It's also called monkey patching. It's not without its risks but all I am doing is describing it here in the context of reflection, of which it is an example.

Serx
Definitely a powerful feature, but are you sure it's an example of reflection? I don't know if working with self is, strictly speaking, "reflection." I thought reflection was more like when you interrogate classes and objects at runtime to find out what they are and what they can do.
Ethan
Yeah, this is not really a feature of reflection, but still a cool feature.
Derek P.
I understand the source of your confusion. I will edit my response to explain my reasoning for citing class reopening as an unambiguous example of reflection.
Serx
In your code sample above, where you reopen the class "Integer" to add the method "moxy," are you saying you're doing that "at runtime?" I think your idea of the definition of "runtime" might be mistaken.
Ethan
I'm no Ruby expert but doesn't it have an eval function? So you could convert that to a string and run it at "runtime".
jmucchiello
A: 

It refers mainly at how easy is to inspect and modify internal representations during run-time in Ruby programs, such as classes, constants, methods and so on.

Most modern languages offer some kind of reflective capabilities (even statically typed ones such as Java), but in Ruby, it is so easy and natural to use these capabilities, that it really make a real difference when you need them.

It just makes meta-programming, for example, an almost trivial task, which is not true at all in other languages, even dynamic ones.

Dema