Websela

Object Models – Smalltalk, Ruby, & JavaScript

Posted on: August 14, 2013

I read “Metaprogramming Ruby” asking myself why Rubyists didn’t have a debugger like we have. What was different about our object model that allowed us to have our debugger?

It’s not just a deeper object model. It’s a more rigorous implementation of the language. Ruby has a “create as needed” philosophy. Smalltalk has a “consistency of implementation” philosophy.

The difference between Smalltalk, Ruby, and JavaScript is a question of how extensively the language designers wanted to create an objective reality against which any program could be evaluated. That seems to me to be the basis of reflection. You need something against which to judge something else.

Smalltalk has a full objective reality, as a result of a deeper object model and rigorous implementation. Ruby has a partial objective reality, which is created only as you need it. JavaScript has no objective reality whatsoever. It’s a DSL makers paradise.

I don’t think there is a language called JavaScript. More, there is a galaxy of libraries and frameworks, all DSLs, that create their own reality and cannot relate to each other. Do jQuery, node.js, or Angular.js know how to play together, or are they just islands?

The things that stand out to me about Ruby are instance variables and eigenclasses. Chapter 5 of the Bluebook says metaclasses were created to give classes customizable initialization. That appears to me to be what Ruby doesn’t have – constructor methods. It has :new and :new() (OK, ActiveRecord has :create for automatic generation of setters and getters). You cannot initialize an object and set the values of instance variables in one message.

If I read this rightly, you need to initialize instance variables. i.e.:

        
             class MyClass
                def my_method
                    @v = 1
                end
             end 

             obj = MyClass new 
             obj.my_method

On page 35 of “Metaprogramming Ruby” it says:

“If Bill, hadn’t called obj.my_method(), then obj would have no instance variable at all.”

Initialization for ivars. That’s interesting.

Constructor methods in Smalltalk are class side methods. You can add class side methods in Ruby. Each time you do so, an object called an eigenclass is created. This follows the “create as needed” philosophy that I see as Matz’s attitude to language design. As opposed to the “consistency of implementation” that I see as Kay’s.

And that’s why we have a debugger as we do an nobody else does. We have a deep – perhaps four tier deep – object model that is quite rigorously implemented. These two things seem to me to provide a greater objective reality against which a specific program can be judged. I think that is a definition of reflection. A layer of abstraction provides a basis of comparison.

Ungar’s paper “SELF: The Power of Simplicity” describes the SELF language from which JavaScript gets its prototypal inheritance. In the paper he compares SELF to Smalltalk-80. He suggests that an advantage of SELF is that it eliminates meta-regress (i.e. class of class of class):

“No object in a class-based system can be self sufficient; another object (its class) is needed to express its structure and behaviour. This leads to a conceptually infinite meta-regress: a point is an instance of class Point, which is an instance of metaclass Point, which is an instance of metametaclass Point, ad infinitum. On the other hand, in prototype-based systems an object can include its own behaviour; no other object is needed to breathe life into it. Prototypes eliminate meta-regress.” (page 5)

It’s an interesting point. It sounds so reasonable. And I’ve resented the Smalltalk object model for years, as an oppressive Mobius strip. But now that I understand it, I think it provides an objective, underlying reality that I find quite reassuring. To have a similarly reassuring substructure in JavaScript, you need to invent it yourself. And that’s what the ever expanding galaxy of JavaScript frameworks is doing, ad infinitum.

Advertisements

9 Responses to "Object Models – Smalltalk, Ruby, & JavaScript"

See also Dart, the project that aims to bring such tools to the JavaScript ecosystem.

https://www.dartlang.org/docs/technical-overview/

Good point. I hadn’t thought of that.

I stumbled upon this post while vanity-Googling for “Metaprogramming Ruby”. Great read, especially when you compare the Ruby and the Smalltalk culture. Thanks for the insights!

Whoa. I’m delighted you think so. Thank very much for reading it.

I would frame the comparison between Smalltalk and Ruby a little differently. Their object models are mostly the same, but their execution environments are radically different. Smalltalk’s object model isn’t really “deeper” (ignoring Ruby’s syntactic sugar), but the image allows tools to reflect on a static snapshot of the code.

As you point out, in Ruby it is normal for classes to change at runtime as code is evaluated. In contrast, Smalltalk doesn’t distinguish between development- and run-time. There is only the image with the current state of object memory. I suspect most programmers would be puzzled if you explained that Smalltalk, the canonical object-oriented language, has no syntax for defining classes and methods.

The difference is where code generation occurs: by the programmer interacting with the image, or the runtime evaluating a program.

Here are some posts by Avi Bryant that compare the tradeoffs made by Smalltalk and Ruby:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2002-April/038077.html
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/79078
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/124927

Excerpts from the last post:

“In Ruby, as in Lisp, a program is a narrative that builds up a particular state (of classes and methods) that then gets used for the computation. […] A Smalltalk class browser, however, is designed to edit the current state of the program. *How* the state gets built up is never captured: it’s done by user interaction with a live program over a long period of time.”

Wow. This is great stuff. Thank you for taking the question seriously and providing this great grist for me to chew upon. I hope you can attend the next meeting of the TSUG on the 9th of Sept. to explore these ideas further.

Actually, you *can* initialize a Ruby object and set its instance variables in one message. E.g.,

class MyClass
# In Ruby, #initialize is called automatically for a new instance
def initialize(v)
@v = v
end
end

obj = MyClass.new(1) # Creates an instance with @v set to 1

It’s true, however, that Ruby objects don’t have a relatively static “shape” (to use the Smalltalk term); i.e., an explicit list of instance variables.

Great example! I stand corrected.

IMHO develop with Smalltalk is very productive and offers an awesome developer experience – until someone needs to include 3rd Party libraries (classes). There is not only one Smalltalk. Each smalltalk implementers play their own game. Most likely you can not use a library, parcel, package, etc from different smalltalk implementation, nor different version.
So talking about islands – each version of the different smalltalk implementations are islands for me. I.e. try to reuse classes written for e.g. squeak 2 in some other smalltalk system, or version. Smalltalk makes really fun, is clean, productive, and also frustrating for app developer.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: