Object: Identity vs. Environment

Richard A. O'Keefe ok at cs.otago.ac.nz
Thu Jun 12 00:44:56 UTC 2003


I wrote:
	>Have you read the implementation of #respondsTo: ?

Nevin Pratt <nevin at smalltalkpro.com> replied:
	Which implementation are you referring to?  The one in Object?

What do you mean, "which one"?  Squeak as distributed _has_ only one
definition of #respondsTo:; aside from the one in Object, there is no other.
I don't have any copies of Squeak before 2.7, but from 2.7 until 3.5,
Squeak has only ever shipped with ONE definition of #respondsTo:.

Unsurprisingly, it's practically identical to the one in VisualWorks:

    respondsTo: aSymbol
        "Answer a Boolean as to whether the method dictionary of the
         receiver's class contains aSymbol as a message selector."

        ^self class canUnderstand: aSymbol

Somewhere in the history of VisualWorks someone added the words
"a Boolean as to".  If this implementation, and this comment, don't
go all the way back to Smalltalk-80, I'll be surprised.

I rather like the comment in the VAST5.5 guide:
   "The use of respondsTo: and isKindOf: often indicate a problem in
    the architecture of a system."

	You actually read the comments?

Of course.  In this case, the comment is a life-saver; without it you
might think that #respondsTo: answers "does this object respond to
this selector", but it doesn't.  It's about as helpful as a comment
can possibly be.

	My eyes usually just scan right past them, 
	and I don't even notice if a comment is correct or not anymore.
	
My eyes usually rest in disgust on the template that shows someone
didn't bother writing a class comment, and I decide not to use that
class.  If someone didn't understand their code and its likely uses
well enough to write brief useful comments, why should I imagine that
they understood it well enough to write code that works?

	Yes... that method comment is misleading.

But it ISN'T misleading.  It tells the absolute truth.
I have faint memories of reading essentially the same advice in a
Smalltalk book once.  It might even have been one of the Goldberg
books, but my copy of "ST80 the language..." has walked.

	It describes the implementation details as implemented in
	Object, rather than the actual responsibility of the method.

There is nothing anywhere in Squeak to justify a claim that the
*actual* responsibility of the method is other than what it actually
*does*.

I've checked all the Smalltalk manuals I could find.
The only one to actually explain #respondsTo: was GNU Smalltalk.
(For some reason, texi2dvi and texi2html choke on the .texi files,
and info doesn't like the .info files.  I have no idea why.)
The documentation in GNU Smalltalk is unforgiveable:

    @meindex respondsTo:@-
    @item respondsTo:@- aSymbol
    Returns true if the receiver understands the given selector
    ...
    @meindex canUnderstand:@-
    @item canUnderstand:@- selector
    Returns true if the instances of the receiver understand the given
    selector

This leaves the baffled reader wondering what "understands" means;
the reader's guesses are extremely unlikely to include the actual
answer...

	That's unfortunate.  And the wrong
	information for a comment to contain, in my opinion.
	
Well, *this* is what *I* call unfortunate.
It's the implementation of #resondsTo: in GNU Smalltalk.

respondsTo: aSymbol
    "Returns true if the receiver understands the given selector"
    ^self class canUnderstand: aSymbol

You'll notice that it's the same *implementation* as the traditional
one, but the comment now describes what you seem to say is the actual
responsibility.  The two disagree.  Someone wanting to know whether
they can use #respondsTo: will stop reading here, having been assured
that yes, they can.  But they can't.  To find out that they can't,
they'd have to go on and read #canUnderstand:.

What *is* "the actual responsibility of the method"?
The only reasonably authoritative source available to me is the
ANSI Smalltalk standard.

    5.3.1.15
	A message to perform a selector, <code>selector</code>',
        for a given receiver will result in a "message not understood"
        condition if and only if the value of
	    <code>receiver respondsTo: selector</code>
        is <i>false</i>.

    5.3.1.19 Message: respondsTo: selector
	Definition: <Object>
	    Return <i>true</i> if the receiver has a method in its
	    behavior that has the message selector <code>selector</code>
	    Otherwise return <i>false</i>.

That is, according to the ANSI Smalltalk standard,
"the actual responsibility of the method" is EXACTLY WHAT THE COMMENT
IN SQUEAK SAYS IT IS.

	>I repeat, it *never* tells me what *I* really want to know.
	
	Well, *never* is a bit too strong.

No it isn't.  I make no claim about whether it's ever what _other_
people want.  I claim that it's never what _I_ want, and that is 100% true.

	And, that problem can exist with any 
	message, not just #respondsTo:.  Just fix it.
	
But we CAN'T "fix" respondsTo: without breaking 23+ years of historical
use and compatibility with the ANSI standard.

Actually, I tell a lie.  The ANSI requirement in 5.3.1.15 is
unimplementable.  Suppose I have

    Bar>>foo
      (some extremely complicated condition which is always true)  
          ifTrue: [MessageNotUndetstood new
		     message: (Message selector: #foo)
		     signal].

Now (Bar new respondsTo: #foo) will answer true, but
(Bar new perform: #foo) will result in a message not understood condition.
Why does the ANSI ST standard fall apart every time I poke it?

Can we agree to these propositions:

    (1) It is useful, even *important*, to have a way of finding out
        whether an object includes a definition (any kind of definition)
        of some selector in its behaviour.

    (2) The ANSI Smalltalk standard, and 23+ years of Smalltalk tradition,
        give the name #respondsTo: to that method.

    (3) #respondsTo: is often used in the idiom
        (anObject respondsTo: #foo:bar:)
            ifTrue: [anObject foo: x bar: y]
            ...
            
    (4) For that idiom to work reliably, what's really needed is a method            
        which can tell the difference between a method whose body is
	(    self subclassResponsibility
        or   self shouldNotImplement
        or   self error: '...'
        ), which is NOT normally thought of as "responding", and other
        method bodies.  Of course, determining whether a method will
        always raise an error before doing useful work requires
        solving the Halting Problem, so I don't expect that.  But the
        *intention* of the three patterns I have shown is to make it
        clear that the method is NOT supposed to be called; it's
        fair to ask that anyone who wants their method to be rejected
        by #canHonestlyUnderstand: or #honestlyRespondsTo: should use
        one of those three patterns.

    (5) While such a method would be useful, #respondsTo: is not that
        method, never has been, and according to the standard, must
        never be.
            
    (6) The existence of the idiom mentioned in (3) shows that the
        name is misleading.

    (7) We cannot change the behaviour of #respondsTo: without losing
        ANSI/VW/VAST/GST/ST-80 compatibility, and we cannot change the
        behaviour of #canUnderstand: without losing VW/VAST/GST/ST-80
        compatibility, and more importantly, without confusing people
        who might read the few textbooks that mention #respondsTo.

	>Given the intimate connection between #respondsTo: and #canUnderstand:,
	>if one is overriding #doesNotUnderstand: and #respondsTo:, shouldn't
	>#canUnderstand: be overridden too?
	
	No, I don't think so.  The fact that Object>>respondsTo: uses 
	#canUnderstand: is an implementation detail that nobody outside of 
	Object>>respondsTo: should even need to know about.

Well, no.  The point is not the #respondsTo: *uses* #canUnderstand:
but that THEY HAVE THE SAME SEMANTICS.

	In other words, from the point of view of external consumers,
	there is no connection between those two messages.
	
Yes there is.  Except for one starting at an object and the other starting
at a class, they have the same meaning.  *From the outside*, we expect
    anObject respondsTo: aSelector
and
    anObject class canUnderstand: aSelector
to have exactly the same meaning.  If someone overrides #respondsTo:
without overriding #canUnderstand: in the same way, that introduces
an inconsistency.

	Also, consider that we need a message that asks if a method is in the 
	method dictionary* of the receiver class,

Careful reading here:  "the receiver (which is a class)".  Fine.

	or any superclass of the receiver class.  And, such a message
	shouldn't care what messages are overrides.  It only cares about
	what is actually in the method dictionaries.
	
	What do you propose the name of that message should be?
	
Well, an *intention-revealing name* would have been #includesSelector:

	I propose #canUnderstand: for such a message, since that's what
	it does.

I propose #canUnderstand: on the grounds of compatibility with past and
current Smalltalk systems.  It's a really dreadful name!  Compatibility
is the _only_ excuse I'd accept for putting up with such a misleading
and unhelpful name.  But it's a good reason, within reason.

	But I'm willing to entertain the idea that #canUnderstand:  is
	inappropriately named, if you think you have a better name for that 
	particular responsibility.
	
#includesSelector: is a far better name.  Light years better.
It just doesn't happen to be the name that other Smalltalks use/have used,
and I don't like breaking things.

That's why in the message Nevin Pratt was responding to, I proposed
*new* names

    Object>>honestlyRespondsTo: aSelector
        "Does the receiver's behaviour include a 'genuine' definition
         for aSelector?  Method bodies of the forms
	    self subclassResponsibility
	    self shouldNotImplement
	    self error: '...'
         are understood as ways of saying that the selector is NOT
         really defined; they are not counted as 'genuine' definitions."
        ^self class canHonestlyUnderstand: aSelector

    Behavior>>canHonestlyUnderstand: aSelector
        "Similar comment"
        ^(self canUnderstand: aSelector) and: [
            the implementation doesn't match one of the three
            patterns listed above]

I don't claim any great merit for those names, other than if someone
goes looking for the old names, they'll find these, and be aware that
they have a choice to make.



More information about the Squeak-dev mailing list