This is the solution I am going with now. In fact, if Ruby itself had this
sort of "interface identification" built-in, it would suit me perfectly. I
don't believe that respond_to? really tells you much about an object's
interface. Two objects can respond to the same method name, but do
COMPLETELY different things. Duck typing doesn't work, and checking
respond_to? doesn't work. The only way to REALLY know if an object
implements a certain interface is if you can positively identify it directly.
Somehow, the object has to say "I implement the hash interface." Whether
that's just a simple flag, or if Ruby can somehow match it's methods to an
A protocol imposes constraints to the acceptable behavior of the object, so
as you correctly pointed out, the signatures alone can't suffice. I
believe the current state of the art can discover many implicit
invariants in the code, but it can't infer them all. Even if it could,
at some point you might have some invariants that hold only due to the
particular implementation used, it is still up to the programmer to
specify whether some invariant belongs to the interface or is just a
coincidence.
Therefore, what you seem to want still requires the programmer to tag the
objects somehow.
Once we get to this point, we can think of ways to do it. There's two
things to consider: tagging objects and checking for some tag.
One can trivially use Ruby's mix-in mechanism to declare conformance
with a given interface, and then use some magic to allow
def_typed :my_method, HashProtocol, FooProtocol do |foo, bar|
... foo, bar have been declared to satisfy HashProtocol & FooProtocol
end
or something like
typesig HashProtocol, FooProtocol # Types for next defined method
def my_method(foo, bar)
The latter (and many other ways to do type checking) is implemented in
http://people.freebsd.org/~eivind/ruby_types/types.rb .
Regarding including this in the language:
I have argued above that ruby wouldn't be able to do internally much more
than the current solutions (in particular, it is also possible to make
sure that method redefinition doesn't break conformity with a declared
interface in pure-Ruby/C-extension solutions). If it won't be any more
powerful, the possible advantages that could justify including it I can
think of are
(1) convenience
(2) speed
(3) sanctioning this practice as belonging to "the Ruby way"
Regarding (3), it is up to matz to define what is and what isn't Ruby,
so we can't comment.
As for (1), Ruby's syntax is "extensible" thanks to blocks, as shown
in
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/99660 .
We'd have to compare syntaxes at some point, but it's not clear a-priori
that a sanctioned syntax in the core must be necessarily better (i.e.
a good solution doesn't necessarily require changes in the parser).
Finally, as far as speed is concerned:
in [85895], matz explains that he doesn't know how to make interface checking
efficient. In [85888] you proposed an interesting interface checking
system and concluded that "Performance hit at runtime is merely a very short
interface table lookup". However, I believe you didn't consider the
following:
* per-object conformity tables are very expensive, memory-wise: one
additional word per object pointing to the table (if you don't put
it in the R* structure and store it in the iv_table instead, it'll be
slower) , plus the table itself.
* per-class conformity tables would have a lower mem. impact, but make
singleton classes a bit more complex to handle and most importantly
would make interface checking slower cause you'd have to walk up the
inheritance chain (caching couldn't be as effective as method caching
cause there's more objects than distinct methods)
In other words, there's no real way to implement interface checking
much faster than
http://mephle.org/StrongTyping/.
That being said, in the future it might be possible to do constraint
propagation (+ partial evaluation) at compile/parse time + method
specialization, which could make everything significantly faster.
Summarizing, there's arguably little gain in adding this sort of interface
checking to Ruby's core _as of now_. There's a number of solutions that
work fairly well and some that are as fast as you can get today.
You have stated before on this thread that tagging objects is a "kludge";
I cannot agree with that, or more precisely, I don't see it as any
worse than the proposed modifications to Ruby we've seen in the past,
since tagging is about as efficient as they would be, and the available
"interface tagging" implementations have pretty convenient syntaxes
(although that's somewhat subjective, but I think we can agree on the fact
that the "best" syntax doesn't necessarily involve changes in the parser).
interface description, or whatever, I don't care. All I want to know is if
an object implements a certain interface. I don't care about ancestry, what
methods it responds to, and I don't like just calling the object's methods
and crossing my fingers. Errors slip through quietly like that, and except
for people who don't really care about that sort of thing, it doesn't work.
If you need a solution that badly, I'd recommend that you use types.rb
(more flexible) or StrongTyping (faster) for the time being.
I don't think Ruby will do this "natively" for some time...
It is my understanding that some large systems have been implemented in
Smalltalk; I'd like to know if they solved those problems through
interface declaration + checking, more stringent procedures or some
other technical solution.
PS: I am personally more interested in concrete type discovery (for speed)
than in generic type inference.
--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com
Tut mir Leid, Jost, aber Du bist ein unertraeglicher Troll.
Was soll das? Du *beleidigst* die Trolle!
-- de.comp.os.unix.linux.misc