Conflicts between using respond_to? and extending Ruby

Hi–

I recently cam across an interesting conflict between open-uri.rb and
Facets rendition of kernel/metaid.rb. Facets defines a general
extension Kernel#meta, and open-uri defines OpenURI::Meta#meta. open-
uri uses OpenURI::Meta to extend StringIO via singleton. This is all
fine, but then open-uri checks to see if a StringIO object has been
extended by doing:

io.respond_to? :meta

And that’s where the problem lies, b/c if you’ve loaded ‘facets/kernel/
metaid’ you’re going to get a false positive here. Now the best remedy
is open-uri to be more precise:

io.is_a? OpenURI::Meta

That fixes the the problem. But it raises an interesting question.
I’ve used #respond_to? myself from time to time thinking it was oh, so
duck-type kosher; never realizing that it might clash with general
extensions.

So where lies the fault in this conflict? Are extensions the bad guy,
or is respond_to? really not a good oop concept? Or…?

T.

Hi –

On Mon, 22 Oct 2007, Trans wrote:

So where lies the fault in this conflict? Are extensions the bad guy,
or is respond_to? really not a good oop concept? Or…?

I think this is just the age-old issue about adding methods to
existing classes and hitting conflicts. #respond_to? is relatively
dumb; it can’t tell you what the method actually does. I think of it
as an important tool for “soft” duck typing, in contrast with “hard”
duck typing where you just send the object the message.

What does your Kernel#meta do? If it’s what’s usually called
#singleton_class, you might change it to #singleton_class :slight_smile: Or
something like that (#metaclass, if you’re into that terminology) – a
little more descriptive and less likely to clash. There’s no perfect
solution, though. Using #extend on specific objects, instead of adding
methods to Kernel, could make clashes much less likely, though if you
happened to add #meta to a StringIO object via #extend, you’d still
have the same problem.

David

On Oct 22, 7:29 am, “David A. Black” [email protected] wrote:

uri uses OpenURI::Meta to extend StringIO via singleton. This is all

dumb; it can’t tell you what the method actually does. I think of it
as an important tool for “soft” duck typing, in contrast with “hard”
duck typing where you just send the object the message.

That’s interesting. It makes me wonder if it’s worth “hardening” with
something like:

respond_to?(:meta, OpenURI::Meta)

So that Ruby will check that it would respond to a #meta that’s
defined in OpenURI. But yea, really, I agree with you. I never really
realized it before, but respond_to? is pretty weak.

What does your Kernel#meta do? If it’s what’s usually called
#singleton_class, you might change it to #singleton_class :slight_smile: Or
something like that (#metaclass, if you’re into that terminology) – a
little more descriptive and less likely to clash.

Sort-of, but it wraps the singleton in a Functor, so you can call
methods against it as if you had opened it up yourself. For example:

class X
meta.attr :x
end

Defines a class attribute.

There’s no perfect solution, though. Using #extend on specific objects, instead of adding
methods to Kernel, could make clashes much less likely, though if you
happened to add #meta to a StringIO object via #extend, you’d still
have the same problem.

Indeed.

T.

On 10/22/07, David A. Black [email protected] wrote:

On Mon, 22 Oct 2007, Trans wrote:

metaid’ you’re going to get a false positive here. Now the best remedy
or is respond_to? really not a good oop concept? Or…?

I think this is just the age-old issue about adding methods to
existing classes and hitting conflicts. #respond_to? is relatively
dumb; it can’t tell you what the method actually does. I think of it
as an important tool for “soft” duck typing, in contrast with “hard”
duck typing where you just send the object the message.

Okay, I’m claiming stake to coining what I hope becomes as much of a
meme as duck typing:

http://talklikeaduck.denhaven2.com/articles/2007/10/22/chicken-typing-isnt-duck-typing


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Trans wrote:

respond_to?(:meta, OpenURI::Meta)

I’m sorry, but that looks just so wrong to me. Take the case on .each.
You don’t test if an object respond_to?(:each, Enumerable), you just
need the .each.
I don’t think there’s a solution to the problem as you sacrifice one or
the other thing. You can’t know by the name of a method whether it does
what you want or not. So either you jump into the cold water and assume
it does or you sacrifice flexibility and test if it’s derived from
something you know.

Regards
Stefan

Hi –

On Mon, 22 Oct 2007, David A. Black wrote:

What I’ve always called the soft/hard duck typing distinction isn’t
quite the same as what you’re calling the chicken/duck distinction,
though, in the sense that I rule is_a? and kind_of? completely out of
bounds as duck typing of any kind.

I didn’t put that very clearly, since you do too. What I mean is, it’s
like this:

Rick:

Chicken-typing
is_a?/kind_of?
respond_to?
Duck-typing
obj.message

David:

Class-checking:
is_a?/kind_of
Soft duck:
respond_to?
Hard duck:
obj.message

or something.

David

Hi –

On Mon, 22 Oct 2007, Rick DeNatale wrote:

duck-type kosher; never realizing that it might clash with general

Okay, I’m claiming stake to coining what I hope becomes as much of a
meme as duck typing:

http://talklikeaduck.denhaven2.com/articles/2007/10/22/chicken-typing-isnt-duck-typing

Be careful what you wish for :slight_smile: In any case, I’m glad to have
provided the impetus, if not the name.

What I’ve always called the soft/hard duck typing distinction isn’t
quite the same as what you’re calling the chicken/duck distinction,
though, in the sense that I rule is_a? and kind_of? completely out of
bounds as duck typing of any kind. Duck typing, as I understand it
from various writings by, and exchanges with, Dave T., starts
where is_a? leaves off. respond_to? starts to enter the duck-typing
orbit, in the sense that at least it’s focused on the object and its
capabilities, rather than its class/module ancestry (and that’s the
most decisive line to cross). Since it still falls short of simply
asking the object to do something, I consider it a “soft” form of duck
typing. It’s object-driven, but not atomic.

David

On 10/22/07, David A. Black [email protected] wrote:

typing. It’s object-driven, but not atomic.
One difference between kind_of? and respond_to? is that it’s slightly
more likely that a particular method or methods mean what the chicken
typer expects when using kind_of? than respond_to?, since kind_of? is
testing an implementation relationship, but that’s by no means
guaranteed.

The notion of ‘type’ held by the user of an object is often more
complex and or general than just being in a particular implementation
hierarchy, or responding to a certain set of verbs at the lexical
level. So I don’t see so much of a distinction between respond_to?
and kind_of?


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hi –

On Tue, 23 Oct 2007, Rick DeNatale wrote:

most decisive line to cross). Since it still falls short of simply
complex and or general than just being in a particular implementation
hierarchy, or responding to a certain set of verbs at the lexical
level. So I don’t see so much of a distinction between respond_to?
and kind_of?

The distinction I see is proximity to the object. respond_to? is
asking the object about its capabilities, whereas kind_of? is asking
it about its ancestry. So respond_to? is a tighter fit with the object
as it is at a given point in runtime.

David

On Oct 22, 2007, at 10:39 AM, David A. Black wrote:

The distinction I see is proximity to the object. respond_to? is
asking the object about its capabilities, whereas kind_of? is asking
it about its ancestry. So respond_to? is a tighter fit with the object
as it is at a given point in runtime.

it all depends - consider the case of trying to tell wether or not a
hash, array, or rbtree is passed to a method. you can’t use
‘respond_to?("[]")’, ‘respond_to?(“size”)’, etc. you can sometimes
pick the ‘right’ method but, other times you cannot and

case obj
when Array

is safer and more accurate. i think it really depends on the use
case - i personally use both.

cheers.

a @ http://codeforpeople.com/

Hi –

On Tue, 23 Oct 2007, ara.t.howard wrote:

‘respond_to?(“size”)’, etc. you can sometimes pick the ‘right’ method but,
other times you cannot and

I don’t think there even is a right method for this purpose; I don’t
think respond_to? ever enters into the picture when you want to know
the class of an object. It doesn’t convey that information.

case obj
when Array

is safer and more accurate. i think it really depends on the use case - i
personally use both.

It does indeed depend; they do totally different things. I was
describing the differences, specifically in the context of duck typing
(or alternatives to duck typing): respond_to? gives you information
about an object at a given moment, and kind_of? tells you about its
ancestry.

David

On Oct 22, 2007, at 11:26 AM, David A. Black wrote:

case obj
when Array

is safer and more accurate. i think it really depends on the use
case - i personally use both.

It does indeed depend; they do totally different things.

not entirely - they both allowing pre-testing to see if code is going
to work or explode…

I was
describing the differences, specifically in the context of duck typing
(or alternatives to duck typing): respond_to? gives you information
about an object at a given moment, and kind_of? tells you about its
ancestry.

well sortof:

OpenStruct.new.respond_to?(:foo) #=> false

OpenStruct.new.foo() #=> nil

as i said, i think it’s 100% situational and you really can’t make
blanket rules.

cheers.

a @ http://codeforpeople.com/

Trans posted a reply to my article saying that I was being too hard on
is_a?/kind_of? I responded there but thought that I should repeat
what I said here:

Trans said:
I think you’re a little too hard on is_a?/kind_of? though. I don’t
think they fit the “chicken” typing character quite as well. Yes, they
aren’t 100% in a dynamic language such as Ruby’s, however they are
much much more dependable than respond_to? b/c modules and class
intend to represent an encapsulation of behavior. If we ask ‘is_a?
Enumerable’, we can be pretty sure that we are working with something
that responds to #select or what have you as the way we’d expect.

My reply:
True enough, but I wouldn’t say much more dependable. Even within an
implementation hierarchy, the signature and even the meaning of a
method can change. Consider, for example how the details of the each
method vary depending on whether the enumerable is, say, a Hash, vs.
an Array. You’re typically expecting certain things to be yielded to
the block by each, and neither kind_of? or respond_to? helps predict
either the arity for the block expected, or what will be yielded.

And the flip side argument against chicken typing with kind_of? is the
false negative problem. There are interesting cases where unrelated
classes implement similar methods or families of methods.

And sometimes the method similarity can be complex, making determining
substitutability difficult. Consider how many classes implement some
form of [], and how many variations of parameters there are affecting
the semantics, even within the same class.

While some of the chicken typing persuasion might look at this as a
mess needing to be cleaned up, duck typers see it as the powerful
flexibility that gives Ruby it’s agility when coupled with the right
approach and tools.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Oct 22, 2007, at 5:10 AM, Trans wrote:

extensions.

So where lies the fault in this conflict? Are extensions the bad guy,
or is respond_to? really not a good oop concept? Or…?

T.

respond_to? + arity it sometimes better. other alternatices are to
mark objects with modules

module Marker; end

object.extend Marker

if Marker === object

so you have a more controlled environment - facets could easily use
this approach. btw, this is something pervasives addresses and which
is use quite heavily in meta-programming: for production code i think
it’s best not to ask objects if they do ‘x’ or ‘y’ using either
‘respond_to?’ OR come ‘is_a?’ test, rather you should, if possible,
simply ensure that they do. here is an example

cfp:~ > cat a.rb
class BlankSlate
instance_methods.each{|m| undef_method m unless m[’__’]}
end

bs = BlankSlate.new

Object.instance_method(‘instance_eval’).bind(bs).call{ @a = 42 }

class << bs; attr :a; end

p bs.a #=> 42

cfp:~ > ruby a.rb
42

so, here, we simply force the object to ‘respond_to?’ the method we
want in exactly the way that we want it to. this isn’t always an
option but, imho, any general purpose library should at least attempt
this approach - attributes.rb just just this so as to make the
smallest amount of assumptions about an objects type/behavior as
possible.

cheers.

a @ http://codeforpeople.com/

Hi –

On Tue, 23 Oct 2007, ara.t.howard wrote:

It does indeed depend; they do totally different things.

not entirely - they both allowing pre-testing to see if code is going to work
or explode…

Pre-testing is what you do, not what the method does :slight_smile:

OpenStruct.new.foo() #=> nil
You’re a hard task-master :slight_smile: OK, I’ll try again:

respond_to?(:x) gives you information about an object at a given
moment – namely, whether or not any of the classes or modules
currently in an object’s method lookup-path has a method “x” defined
(including the object’s singleton class).

kind_of?(m) tells you about an object’s ancestry – namely, whether or
not a class or module called m is among its ancestral classes and
modules.

And yes, I know you can do:

s = “hi”
def s.respond_to?(x)
true
end

and I think people have sometimes even advocated this for OpenStructs.
But the above is as watertight as I can get :slight_smile:

as i said, i think it’s 100% situational and you really can’t make blanket
rules.

I think we’re talking at cross purposes; I wasn’t suggesting rules,
blanket or otherwise, just commenting on the difference(s) between
respond_to? and kind_of?

David

On 10/22/07, ara.t.howard [email protected] wrote:

so you have a more controlled environment - facets could easily use
this approach.

On 10/22/07, ara.t.howard [email protected] wrote:

so you have a more controlled environment - facets could easily use
this approach.

I’ve been using something similar to this approach by using modules to
represent sets of behaviours which a class should have. So you end up
with
class definitions like this (bogus example):

class Duck
include CanFly
include CanQuack
include CanSwim
end

i.e. composing the class definition from the set of behaviours or
protocols
it satisfies.

Checking whether an object will fulfil your expectations then becomes:

if donald === CanQuack

This is a much stronger guarantee of behaviour than :respond_to? and
still
qualifies as duck-typing in my opinion (i.e. not based on inheritance).

Regards,
Sean

On Oct 22, 4:35 pm, “Sean O’Halpin” [email protected] wrote:

On 10/22/07, Sean O’Halpin [email protected] wrote:

if donald === CanQuack

should be

if CanQuack === donald

That’s interesting. I’ve aliased #include as #is, and #extend as #can.
I should add #can? as well, then:

if donald.can? CanQuack

Or just using Quack:

if donald.can? Quack

T.

On 10/22/07, Sean O’Halpin [email protected] wrote:

On 10/22/07, Sean O’Halpin [email protected] wrote:

if donald === CanQuack

should be

if CanQuack === donald

Which is functionally equivalent to
donald.is_a? CanQuack

it might read better, but I still maintain that checking with is_a? is
still weaker than most folks assume.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On 10/22/07, Sean O’Halpin [email protected] wrote:

if donald === CanQuack

should be

if CanQuack === donald

Hi –

On Tue, 23 Oct 2007, ara.t.howard wrote:

this whole thread is pretty interesting though - it shows how flexible we as
programmers have to be to accommodate the openness ruby. i think some people
would point out this as a weakness because we have to think and talk about
these things but, in reality, it’s only an issue in pretty sticky situations

  • situations i personally don’t attempt to get myself in using less powerful
    languages.

the language choice does indeed change the way we think about problems and,
as such, cannot truly be equivalent for a given task when compared to other
languages - contrary to what turing would tell us :wink:

I’ve always thought that the situation with programming languages is a
lot like that with musical instruments: they (languages or
instruments) all do the same thing (implement algorithms or make
music), but there’s no denying, in either case, that different ones
have very different properties and provide very different experiences.

David

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs