Twelve rules of Ruby

Hi –

On Wed, 15 Jul 2009, Ryan D. wrote:

editing phase)

  1. Classes are objects.

I prefer to tell my students: EVERYTHING is an object, even classes.

I think it conveys the ontology a bit better.

Well – either one is shorthand, in the sense that when actually
teaching the stuff, much more than one sentence is required :slight_smile:

  1. Objects don’t “have” methods; they have the intelligence to resolve
    messages by looking for methods along their class/module lookup
    path.

See #1. Classes, modules, and their anonymous kin have methods.

Of course. Otherwise there wouldn’t be much point looking for a method
along a lookup path of them :slight_smile: That’s really the point of the “has”
thing: objects don’t define or own the methods to which they have
access. At the very least, ownership is class-mediated, including as
between a class object and its own singleton class.

(I know the whole singleton class thing is an implementation decision,
but, at least for now, it’s a decision, rather than an incidental
detail.)

  1. Every instance variable you ever see in any Ruby program belongs to
    whatever object “self” is at that moment, without exception. (Which
    is one reason that understanding how “self” gets assigned is
    absolutely vital.)
  2. A code block is a syntactic construct, not an object.

See #1. EVERYTHING is an object, even blocks.

I don’t consider blocks or argument lists to be objects.

  1. Class variables are not class variables, in the sense of belonging
    to a particular class. They are class hierarchy variables.

I know what you’re getting at, but it might be worth having the contrast of
class instance variables in there so others understand too.

Do cut me some slack :slight_smile: I really wasn’t trying to write a tutorial –
just a list of very succinct, suggestive, almost epigrammatic points.

David

Hi –

On Wed, 15 Jul 2009, Joel VanderWerf wrote:

that one has to hitch descriptions of Ruby’s object model to
descriptions of specific interpreters.

Exactly. There might be a compatible ruby interpreter in which each object
really does “have”, in every possible sense of the word, all of the methods
that obj.send(:methods) lists. The difference between this and MRI with its
own lookup algorithm is unlikely to matter to a beginner, as long as s/he has
a consistent way of talking about the methods that an object responds to, and
how they got that way.

The things I’m talking about are not MRI quirks, though; they’re ways
of modeling why things happen the way they do in (what I still insist
on thinking of as :slight_smile: Ruby itself. I definitely do not believe it’s a
good idea to embargo all observations about the Ruby object model,
beyond “objects have methods”, on the grounds that they’re just
artifacts of MRI.

super is a good example. A lot of people who’ve used Ruby for a while
have a general – or, I should say, specific – idea that super calls
“the same method, in the superclass”.

Consider this code:

module M
def talk; puts “In M”; end
end

class A
include M
def talk; puts “In A”; super; end
end

a = A.new
a.talk # => In M\nIn A

Two observations. First, any interpreter that did not produce the
above results – and for which an account involving method lookup
along a class/module path therefore did not make sense – I would not
describe as a Ruby interpreter. Obviously, if Matz removes classes
from Ruby (or whatever), things will change. But as of today, and the
foreseeable future, Ruby produces that result.

Second, I see no reason to tie my hands, in trying to account for the
behavior of super (and a whole bunch of other things), by ruling out
of court an account of the method lookup heuristics of the Ruby object
trying to resolve a message. I don’t mind if it’s slightly
anthropomorphic, or if parts of it are optimized away by such-and-such
an interpreter. The high-percentage thing, at least for someone
learning Ruby, is to gain the ability both to understand as much code
as possible and to bring as many productive techniques as possible to
bear on writing code.

“has” reverts to being helpful, because it’s the most sensible
irb(main):007:0> s.method :dup # to find out where the method came from
=> #<Method: String(Kernel)#dup>

Yes, that would be chapter 15 :slight_smile:

The thing is, I’m a great non-believer in the “winner take all”,
zero-sum approach to these things. Prompting people to rethink the
notion of an object “having” methods, so that they start to see the
message-resolution heuristics more clearly, in no way entails not
using the techniques you’ve listed here for explanatory purposes. I
don’t feel I have to choose.

I still think of objects as having methods, because Object#methods tells me
what methods an object has.

(Or which ones it will be able to find on its lookup path :slight_smile:

That’s not incompatible with talking about how an object came to have those
methods, and all the different ways that can happen.

Right – thus one circles back to it. Believe me, I’m not the “has”
police :slight_smile: I say “has an x method” all over the place. I just find
that teaching people that there’s more going on – and, specifically,
positioning that “more” as residing under the hood of the “has” – is
very productive.

David

Joel VanderWerf wrote:

accounts; they have the intelligence to perform transactions by
visiting a web site and entering a password.

As you say, the location of such intelligence is a question that can
wait until someone starts poking around in the interpreter.

For a beginner, it’s more important to have a model of how method
lookup works (model in the sense of science, not rails). If the
easiest way of stating this model is in terms of what methods an
object has (and what class they were acquired from), so be it.

Hi Joel,

I agree that a beginner needs a model. It is (IMHO) more important that
the model helps him achieve his goals, than is accurate to the Nth
degree. A rule of thumb - it must not miss-lead.

The art of learning is to update your models as you need them updating,
so you are neither miss-led by their shortcomings or tricked into error.
I see the ability to help with this, as a key skill for anyone who
professes to teach or educate.

Knowing when to discard a model, and how to persuade someone to do it,
are really interesting (and I think important) questions.

Regards

Ian

On Tue, Jul 14, 2009 at 3:36 PM, Ryan D.removed_email_address@domain.invalid
wrote:

On Jul 14, 2009, at 06:16 , David A. Black wrote:

Not sure why they wrapped weirdly (at least on my screen), but here’s
a correctly-wrapped version, I hope.

  1. Classes are objects.

I prefer to tell my students: EVERYTHING is an object, even classes.

Well almost

I think it conveys the ontology a bit better.

  1. A code block is a syntactic construct, not an object.

See #1. EVERYTHING is an object, even blocks.

No, David makes a valid point. There is a difference in Ruby between
a block which is not an object, and a proc/lambda which is.

Also, variables are not objects either, they refer to objects, and
might be part of the state of an object (or on the invocation stack or
…) but they are not themselves objects. This is also true in
Smalltalk were we always used the same mantra of “everything is an
object.” The mantra is not completely true in Smalltalk either.

This latter reminds me of the Daltonian model of atoms as indivisible
lumps, vs the current paradigm in Physics.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Hi –

On Wed, 15 Jul 2009, Ian H. wrote:

whole post). I was going to say "people don’t ‘have’ bank accounts; they

Hi Joel,

I agree that a beginner needs a model. It is (IMHO) more important that the
model helps him achieve his goals, than is accurate to the Nth degree. A
rule of thumb - it must not miss-lead.

A lot of what’s involved in teaching, too, is deciding what not to
say. I think that for many people, when they first try teaching,
there’s almost a feeling of guilt if something occurs to them, in the
course of explaining something, that’s sort of relevant but really
tangential and they don’t say it. But of course if you do say
everything, the student can’t tell that some of it is – so to speak
– in parentheses. There’s an art to cutting yourself off and keeping
to the main path (knowing, of course, that other things can be
revisited later).

The art of learning is to update your models as you need them updating, so
you are neither miss-led by their shortcomings or tricked into error. I see
the ability to help with this, as a key skill for anyone who professes to
teach or educate.

Definitely. It’s not the whole story, but it can be important. Another
interesting point is that sometimes your models have models. For
example, we’re really talking about two things in this thread: the
Ruby object model, and ways of framing and explaining that model so
that people can understand and assimilate it. It’s interesting to
think about how those things interact and combine.

David

Mike S. wrote:

The original example was about how to approach keeping your house cool,
not a manual on the innards of air conditioning. It said, for example,
don’t bother about the walls because the roof is more important.

On that basis my first rule would be:

  1. Don’t worry about any Ruby feature that you don’t need to use. It’s
    very, very powerful but unless you need to write something like Rails or
    you are an astrophysics PhD, then ignore all the fancy stuff.

It’s the Blub thing.

What’s “fancy” depends on one’s exposure. You often can’t know you need
something unless you’ve already spent some time understanding it.

People who come to Ruby from, say, VB, will likely find the notion of
list mapping or injection pretty alien. And they may never see where
they need to use it, because they’ve never had to deal with code that
included those concepts.

To become proficient at a language you need to force yourself out of
your comfort zone and get acquainted with different ways of solving
problems.


James B.

www.jamesbritt.com - Playing with Better Toys
www.ruby-doc.org - Ruby Help & Documentation
www.rubystuff.com - The Ruby Store for Ruby Stuff
www.neurogami.com - Smart application development

Thanks for all the responses. I have to read this more than once to
grasp everything in it though :slight_smile:

  1. Objects don’t “have” methods; they have the intelligence to resolve
    messages by looking for methods along their class/module lookup
    path.

Since methods are bound to a certain evaluation context (ie the object
aka self), isn’t that statement slightly simplicistic in that it
suggests a unidirectional relationship? The word “have” would IMHO
better reflect the reciprocal dependency. But English isn’t my mother
tongue and maybe I got certain details wrong.

On 14 Jul 2009, at 22:00, Rick DeNatale wrote:

Smalltalk were we always used the same mantra of “everything is an
object.” The mantra is not completely true in Smalltalk either.

This latter reminds me of the Daltonian model of atoms as indivisible
lumps, vs the current paradigm in Physics.

Much of this conversation (specifically regarding “has”) reminds me of
the arguments over Bohm’s Implicate Order.

As far as the physics of Ruby methods is concerned, they exist along a
search path and can only be said to belong to an object when that
search path is successfully queried in response to a message. How
that’s modelled under the hood is irrelevant, and whether or not a
method is associated with an object when a message isn’t being applied
is a philosophical question which cannot be answered with certainty.
Quantum mechanics 101 :slight_smile:

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

raise ArgumentError unless @reality.responds_to? :reason

Hi –

On Wed, 15 Jul 2009, lith wrote:

  1. Objects don’t “have” methods; they have the intelligence to resolve
    Â Â messages by looking for methods along their class/module lookup
    Â Â path.

Since methods are bound to a certain evaluation context (ie the object
aka self), isn’t that statement slightly simplicistic in that it
suggests a unidirectional relationship? The word “have” would IMHO
better reflect the reciprocal dependency. But English isn’t my mother
tongue and maybe I got certain details wrong.

As I’ve said in other posts in this thread, the point isn’t really to
get people to stop saying “have”, but rather to get them to start
understanding how the Ruby object model works. Saying “have” is what
we all gravitate toward – which is fine, except it doesn’t pay you
back when you examine it closely trying to figure out what’s really
going on.

Thus the troubleshooting of the “have” model is specifically a way of
getting relative newcomers to Ruby to think more carefully about the
object model.

David

On 7/14/09, Joel VanderWerf removed_email_address@domain.invalid wrote:

have the intelligence to perform transactions by visiting a web site and
entering a password.

As you say, the location of such intelligence is a question that can
wait until someone starts poking around in the interpreter.

Probably. I feel that David is right, well I know he is, on technical
grounds. However I also feel that Rick and Joël are right. I have made
up a model in my mind that reads as follows:

Objects have methods, but if you run into any troubles just remind
that all those methods are stored in objects that happen to be modules
and none in the object itself.
Singleton methods are therefore stored in a singleton class which is
not shared with any other object.

Works for me ;).

Toutes les grandes personnes ont d’abord été des enfants, mais peu
d’entre elles s’en souviennent.

All adults have been children first, but not many remember.

[Antoine de Saint-Exupéry]

I’d explain these concepts in terms of the basic tools that I, even
after years of rubying, still use to explore the capabilities of an
object:

irb(main):001:0> s = “foo”
irb(main):003:0> s.methods.grep /slice/
irb(main):005:0> s.class.ancestors
irb(main):006:0> String.instance_methods(false)
irb(main):007:0> s.method :dup # to find out where the method came from
=> #<Method: String(Kernel)#dup>

I just learned something–I didn’t know you can infer a methods owner
even in 1.8. Nice.

=r