Functions: First or Second Class Citizen?
I was able to grasp pretty quickly what people meant by “Objects being first class citizens” in Ruby. While a “Class” is a technically a special type of object whose class is “Class,” this is a bit reductive. Most Ruby programming, especially in a Rails environment, is organized around classes. Every instance of a class is an object and they all have the same abilities. All objects inherit directly from their class. Their only differences are the literal values stored in instance variables. We can pass objects around and store objects in variables - anything with a return value of any kind (which is itself an object). They have to be literal “things.” A method is not a literal thing - it is a set of instructions that when executed, are turned into a thing.
As Crockford puts it:
The lineage of an object is irrelevant. What matters about an object is what it can do, not what it is descended from.
Because an array is really an object, we can add methods directly to an individual array.
So, for example, if you had an array,
var myArray = [1,2,3];, you could define a function on that array:
1 2 3
person = Person.new. To set a property, or instance variable, we’d need instance method that would allow us to set that instance variable:
1 2 3 4 5
That variable could only be another object - a standard data type like a
Float, or an instance of another class. But it would have to be an object.
No Method errors!), but the value can either be literal data types or functions themselves. That’s why we’re able to make a custom function and assign it to an array. There’s no magic happening with the Array Prototype, we’re simply setting a property on the array, like
length, only our array doesn’t care if the property is equal to a string, a number, an object, another array, or even a function!
Here’s the fun part. We can actually see the evidence! In a browser console, when we write
console.dir(myArray), we get a very interesting output.
1 2 3 4 5 6
The array itself has 3 numbered properties - also known as the indeces of the array (
myArray, for example), a property called
length, and a property called
myLength. That’s the function we made. Undeneath that is
__proto__: Array. I won’t list all the details, but expanding that list will show us every function and property our array inherited from the Array Protoype object that birthed it.
Of course, we could have always defined myLength as a function on
Callbacks! A Good Part!
I’ve been using this stuff without even realizing it. Take this example from one of our Backbone views:
1 2 3 4 5 6 7 8 9 10 11 12