Methods in Ruby: objects or not?
Methods are a fundamental part of Ruby's syntax, but they are not values that Ruby programs can operate on. That is, Ruby's methods are not objects in the way that strings, numbers, and arrays are. It is possible, however, to obtain a Method object that represents a given method, and we can invoke methods indirectly through Method objects.
From The Ruby Programming Language:
You can't really tell.
The only way to get access to a method is to send the #method
message to some object, which will then return a Method
object. But is that Method
object the method itself? Or is it a wrapper around the method? Or is it a converted version of the original method?
You can't know: if you want to look at a method, you have to call #method
, at which point you definitely will get an object. What it was before you called #method
you can't look at, therefore you can't tell.
A couple of datapoints: in Ruby, everything returns a value. What does def
return? It always returns nil
, not a Method
object. And define_method
? It returns a Proc
, but not a Method
(nor an UnboundMethod
). [Note: in Rubinius, def
returns the compiled bytecode of the method, but still not a Method
object.]
If you look at the 4th and 5th paragraphs of Section 6.1 of the Ruby Language Specification (lines 29-34 and 1-5 on pages 5 and 6), you can clearly see that there is a distinction drawn between methods and objects. And if you look at the specification of the builtin classes, you will find that neither Method
nor UnboundMethod
are in there, nor is Object#method
. IOW: you can build a perfectly standards-compliant Ruby interpreter in which methods aren't objects.
Now, blocks OTOH definitely aren't objects. There are many ways to construct Proc
objects from blocks, which then have the same behavior as the original block (lambda
, proc
, Proc.new
, the &
sigil), but blocks themselves aren't objects.
Think about it this way: you can pass a string to File.new
to construct a file object, but that doesn't make a string a file. You can pass a block to Proc.new
to construct a proc object, but that doesn't make a block a proc.
In Ruby, methods and blocks are not, in and of themselves, native or first-class objects. However, they can very easily be wrapped in objects, such that it generally makes no difference.
But try out, and keep in mind the result of,
a = Object.method(:new).object_id
b = Object.method(:new).object_id
a == b
=> false
In Haskell, all values (including numbers as well as lambdas and functions) are first-class values. In every aspect of the language, they are all treated equivalently. This is not the case in Ruby, but it can be approximated.