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 --

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..?

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 Mon, 22 Oct 2007, Trans wrote:

--
Upcoming training from Ruby Power and Light, LLC:
   * Intro to Ruby on Rails, Edison, NJ, October 23-26
   * Advancing with Rails, Edison, NJ, November 6-9
Both taught by David A. Black.
See http://www.rubypal.com for more info!

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/

···

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

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.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Hi --

> 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..?

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.

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 Oct 22, 7:29 am, "David A. Black" <dbl...@wobblini.net> wrote:

On Mon, 22 Oct 2007, Trans wrote:

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

···

On 10/22/07, David A. Black <dblack@wobblini.net> wrote:

On Mon, 22 Oct 2007, Trans wrote:

> 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..?

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.

--
Rick DeNatale

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

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 10/22/07, ara.t.howard <ara.t.howard@gmail.com> wrote:

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.

On 10/22/07, ara.t.howard <ara.t.howard@gmail.com> wrote:

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.

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

···

--
Posted via http://www.ruby-forum.com/\.

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..?

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

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 Thomas, 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 Mon, 22 Oct 2007, Rick DeNatale wrote:

On 10/22/07, David A. Black <dblack@wobblini.net> wrote:

On Mon, 22 Oct 2007, Trans wrote:

--
Upcoming training by David A. Black/Ruby Power and Light, LLC:
   * Advancing with Rails, Edison, NJ, November 6-9
   * Advancing with Rails, Berlin, Germany, November 19-22
   * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details!

should be

  if CanQuack === donald

···

On 10/22/07, Sean O'Halpin <sean.ohalpin@gmail.com> wrote:

  if donald === CanQuack

Hi --

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

···

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

--
Upcoming training by David A. Black/Ruby Power and Light, LLC:
   * Advancing with Rails, Edison, NJ, November 6-9
   * Advancing with Rails, Berlin, Germany, November 19-22
   * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details!

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?

···

On 10/22/07, David A. Black <dblack@rubypal.com> 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. Duck typing, as I understand it
from various writings by, and exchanges with, Dave Thomas, 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.

--
Rick DeNatale

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

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 Oct 22, 4:35 pm, "Sean O'Halpin" <sean.ohal...@gmail.com> wrote:

On 10/22/07, Sean O'Halpin <sean.ohal...@gmail.com> 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.

···

On 10/22/07, Sean O'Halpin <sean.ohalpin@gmail.com> wrote:

On 10/22/07, Sean O'Halpin <sean.ohalpin@gmail.com> wrote:
>
>
> if donald === CanQuack

should be

  if CanQuack === donald

--
Rick DeNatale

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

Hi --

···

On Tue, 23 Oct 2007, Rick DeNatale wrote:

On 10/22/07, David A. Black <dblack@rubypal.com> 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. Duck typing, as I understand it
from various writings by, and exchanges with, Dave Thomas, 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.

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?

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

--
Upcoming training by David A. Black/Ruby Power and Light, LLC:
   * Advancing with Rails, Edison, NJ, November 6-9
   * Advancing with Rails, Berlin, Germany, November 19-22
   * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details!

as i was mentioning to david, my experience is that it just depends: if you are writing something like

   case conn
     when TCPSocket
     when UDPSocket
   end

then is_a? is probably pretty strong - as strong as it possible in ruby since we can always

   def class() Lie end

nevertheless my general rule tends to be along the lines of using class/module/is_a? type checks for built-ins since people who muck that too much get what they deserve if those classes stop working, using 'respond_to?' to keep apis flexible (require as little as possible from client code), and using something like Object.instance_method(:instance-_eval).bind(object).call(*a, &b) when trying to write robust meta-programming type stuff like adding methods to object since i want to *force* compliance iff possible.

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:

cheers.

a @ http://codeforpeople.com/

···

On Oct 22, 2007, at 3:52 PM, Rick DeNatale wrote:

On 10/22/07, Sean O'Halpin <sean.ohalpin@gmail.com> wrote:

On 10/22/07, Sean O'Halpin <sean.ohalpin@gmail.com> 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

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

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/

···

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.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

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

--
Upcoming training by David A. Black/Ruby Power and Light, LLC:
   * Advancing with Rails, Edison, NJ, November 6-9
   * Advancing with Rails, Berlin, Germany, November 19-22
   * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details!

as i was mentioning to david, my experience is that it just depends:
if you are writing something like

   case conn
     when TCPSocket
     when UDPSocket
   end

then is_a? is probably pretty strong - as strong as it possible in
ruby since we can always

   def class() Lie end

Maybe I'm misunderstanding your point, but that doesn't do much.

x = [1,2,3]

=> [1, 2, 3]

x.is_a?(Array)

=> true

x.class

=> Array

def x.class() String; end

=> nil

x.class

=> String

x.is_a?(Array)

=> true

case x
when Array then 'arr'
when String then 'str'
else 'blah'
end

=> "arr"

I ran into this when I thought I was going to be able to use mock/stub
objects and handle is_a?/kind_of?/&c calls by stubbing the response to
class.

···

On Oct 22, 5:09 pm, "ara.t.howard" <ara.t.how...@gmail.com> wrote:

--
-yossef

Hi --

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

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 Tue, 23 Oct 2007, ara.t.howard wrote:

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

--
Upcoming training by David A. Black/Ruby Power and Light, LLC:
   * Advancing with Rails, Edison, NJ, November 6-9
   * Advancing with Rails, Berlin, Germany, November 19-22
   * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details!

ot - but you'll enjoy

   Via 'Musicophilia,' Sacks Studies Music and the Brain : NPR

cheers

a @ http://codeforpeople.com/

···

On Oct 22, 2007, at 4:34 PM, David A. Black wrote:

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.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama