First of all, I think that itis a good idea to be able to check if classes
support protocols. But since ruby does not advertise what and how many
parameters are required for particular methods, the responds_to_protocol?
operation would be pretty weak.

For an example if the IO library were described in smalltalk selector way,
the protocol would be:

foreach:
new:mode:
pipe
popen:mode:
...
write:

In ruby we only get the method name so that if I define a foreach function

def foreach(filename, option1, option2, option3)
...
end

then it would detect my class as supporting foreach when it really is not
compatible.

Steve Tuckner



-----Original Message-----
From: Jim Menard [mailto:jimm / io.com]
Sent: Thursday, October 10, 2002 9:55 AM
To: ruby-talk ML
Subject: Re: Polymorphism, Isomorphism


ptkwt / shell1.aracnet.com (Phil Tomson) writes:

> In article <wsqelazunz9.fsf / io.com>, Jim Menard  <jimm / io.com> wrote:
> >I'm most interested in seeing if an object
> >responds to a handful of particular methods. That's mostly because I only
> >need to know what an object can do when it is an argument passed to a
> >method. It's almost a question with a local scope: "can you do a, b, and
> >c?"
>
> Hmmm.... So you're proposing something like:
>
> ClassA.containsMethods(:foo, :bar, :baz)
>
> or something similar.

Yes. Even better, what about

    needed_methods = [:foo, :bar, :baz]
    ClassA.containsMethods(needed_methods)

needed_methods can be a simple array, or some class that can (as you
suggested) perform set and logical operations.

Are we re-inventing protocols? It feels like it. See the code below.

[snip]

> Or, and now this is getting pretty crazy, what if you get an instance of
> an object which represented the union - this would be something very close
> to multiple-inheritance or maybe mixin (it would probably share all of
> the problems of MI - like if a certain method exists in both 'parent'
> classes which one do you take?).  Or even an instance of a class which
> represents the intersection of two classes - not sure what that would be
akin> to - and again you have the problem of determining which method from
> which class to choose, so perhaps it would be best to stick to lists of
> method names as the result of these logic operations.

Sans the logical and set operators, it sounds like a protocol.

I think this does what I would want.

class Class
    # Respond true only if this class responds to the instance methods
    # contained as symbols in array_of_symbols.
    def responds_to_protocol?(array_of_symbols)
	return array_of_symbols.detect { | sym | !method_defined?(sym) }.nil?

	# This may do the same thing, I'm not sure:
	# return (array_of_symbols & instance_methods).length ==
array_of_symbols.length
    end
end

file_protocol = [:atime, :chmod, :chown]
File.responds_to_protocol?(file_protocol)	# => true
Numeric.responds_to_protocol?(file_protocol)	# => false

You'd need another method to answer the same question for class methods.

This is fun! Yay, Ruby!

Jim
--
Jim Menard, jimm / io.com, http://www.io.com/~jimm/
"The theory of computation states that all automatons can be emulated by a
Turing machine. I have a less abstract but more practical motto: If you can
do it on Intel, you can do it damn near anywhere!" -- Eugene O'Neil