How to ducktype a Hash?

S

Sean O'Dell

Sean said:
Then it's not your problem! Code on, young turk.

No, it IS my problem. My code quietly does some really undesired things
when non-hash-like objects get to this one point in code. I hate this
attitude about typing. I know you mean well, and it's been talked out to
death, but I don't buy the whole thing about "if it has the methods, it
must be fine." It's clearly NOT fine. If an array or a string, both
which have the [] methods I need, get to this one place, I drop a whole
branch of data being passed around. The ideal is to catch it as an
error, and remedy the situation by finding out how the data came in that
way in the first place and prevent it, or perhaps just detect it and
perform some special case. As it is, I can't tell for sure when an
object really DOES act like a hash.

The problem Sean is that even if you know the method has the right
signature you can't guarantee it has the same functionality. It remains
an exercise for the person that wrote the contorted object and is
passing it in to figure out how to make it work with your code. If it
needs to be more hash-like, then let him figure out he needs to pass a
hash. If he can get his weird object to work without it actually looking
or acting like what you think a hash should look like, why penalize him
because he doesn't implement it in a certain way?

That's just a confidence issue. I don't care if the object coming in is
broken. I'm not concerned about catching objects which are implemented
improperly; that's actually very rare. If an object had a signature that
said "I am a hash-like object" that would be fine for me. Duck typing and
checking respond_to? are completely inadequate, and it seems like people
argue those points because Ruby offers nothing else and so what are you going
to advocate? It's those two or rolling your own interface identification
system, which I think is cheesy; that sort of functionality should come from
the framework.

Sean O'Dell
 
S

Sean O'Dell

Duck typing isn't perfect everywhere. With highly type-dependent and
complex systems like REXML, I think it's an ill fit there. However, I'm
glad that in general, Ruby is so dynamically typed -- I do some strange
things that wouldn't work in other languages, and the ability for things
like dRb to be so lightweight is a testament to the philosophy.

Dynamic typing doesn't automatically eliminate the possibility of having some
form of type identification. All typing means in OOP is "interface." All
anyone cares about is, "can this object do these things?" It would be nice
if Ruby addressed that, either in the current release branch or in Rite.
Ruby can be just as dynamic as it is now, and it should still be able to
report what objects implement what interfaces without sacrificing one bit of
flexibility.

Sean O'Dell
 
D

Dave Thomas

The objects are not always a Hash per se, just objects with hash-like
functionality. But, as I said, other objects can slip in too, like
strings
and arrays, which have [] and []= methods, but which don't act like
hashes at
all.

What gives them this hash-like functionality? Can you test for it? And
why would invalid objects be passed in?

Cheers

Dave
 
D

Dave Thomas

Duck typing and
checking respond_to? are completely inadequate, and it seems like
people
argue those points because Ruby offers nothing else and so what are
you going
to advocate? It's those two or rolling your own interface
identification
system, which I think is cheesy; that sort of functionality should
come from
the framework.

I think to be fair you're asking too much of duck typing. It really is
nothing to do with checking anything. It's about assuming, and allowing
objects to behave polymorphically when they aren't actually related in
the class hierarchy.

In your case, this doesn't help, so don't use it.

If the type system of Ruby doesn't help with your application, don't
use it either. I don't: I code in the language appropriate for the work
I'm doing. Over the last three days, I've written in C, Java, Ruby,
TeX, and Emacs lisp.

Cheers

Dave
 
S

Sean O'Dell

IMO, Mr O'Dell needs to consider why he is checking for a
"Hash-like" behaviour. As Nobu (?) suggested, this is more likely
indicated by #each_pair than anything else (Struct behaves that way,
although OpenStruct does not -- perhaps an oversight). After all,
Procs implement #[] -- but they aren't Array *or* Hash (and this is
because there is -- thankfully -- no () operator in Ruby).

I see no problem with checking for #kind_of?(String), or Array, or
Hash -- if you must absolutely have the semantics offered by those
classes, since they are fundamental. However, doing so will limit
your code rather severely, and there are alternatives in most cases.

I'm checking for hash-like behavior, because I have no control over the data
coming in, and it gets converted to Ruby objectsprior to a certain point in
code which expects these objects to be a hash-like object. Right now, that
can mean a hash, a custom class that has hash functionality, the Env object,
or any other object that gets developed in the future with hash-like
functionality.

kind_of?, respond_to? and simply duck typing don't help in this regard. My
only solution is to implement some sort of tagging method and tag Hash, the
custom objects and any objects I can think of, and test for that. That will
work, but it feels like a kludge to run around tagging existing Ruby objects
with a type id.

Sean O'Dell
 
S

Sean O'Dell

This is even worse than object.kind_of(Hash). The whole point of "duck
typing" (as I understand it) is that you don't check if an object has
certain methods. You just use them. Ruby will throw an error if there's
a problem.

Which always sounded fine to me until I was actually exposed to this kind
of "typing." The problem is, the methods [] and []= are there, they just
don't do what I need them to do. Duck typing completely and utterly
don't help, and Ruby has no way to tell me when an object's [] and []=
are hash-like or something else. My solution is going to end being
something like "tagging all objects that I know in advance to be
hash-like, and then looking for that tag at that particular point in my
code." That's a kludge to me.

Well, that's like static typing, which is a kludge to many people.
The "problem" is that Ruby allows you to decide on the level of
type-/class-checking that you want.

No it's not. Static typing is done at load/compile time. I'm not asking for
static typing, just an id on objects that implement certain interfaces.
Those id's can become valid and invalid dynamically, as methods are
added/removed/changed. It depends on how it's implemented.
If this were a static OO language (take Java for example) then you
would have to declare your method as taking a Map parameter, and it
sounds exactly like what you want. Then any piece of code that called
your method would need to ensure it was passing a Map. All that's
doing is "tagging all objects that I know in advance to be map-like,
and looking for that tag at that particular point in your code". The
difference is that the compiler is doing the checking, and the objects
are marked from the outset because they implement a certain interface.

The tag could be a complete lie as far as I'm concerned. I'm not that picky
about the compiler/interpreter actually checking the object to test that it
properly implements an interface. Just having the object be able to say "I
am a hash interface" would be enough. Of course, if actually implemented,
I'm sure the design WOULD check for compliance, but I don't really care.
Static typing is not what I want.
So if interfaces is what you want, then use them. If the fact that
you have to do the work rather than the language makes it a kludge,
then so be it. But Ruby's getting along fine without taking the
narrow road.

It's not a narrow road, it's the road that offers more flexibility and is
harder. It wouldn't affect the current functionality of Ruby one bit.

Sean O'Dell
 
S

Sean O'Dell

If the type system of Ruby doesn't help with your application, don't
use it either. I don't: I code in the language appropriate for the work
I'm doing. Over the last three days, I've written in C, Java, Ruby,
TeX, and Emacs lisp.

That would be sad to deprecate Ruby to just little scripts. It already does
so much very well. But, I have to admit, the more I use Ruby in my larger
projects, the sorrier I am for not going with C++. Ruby gets these projects
off the ground so much faster, but I hit this ceiling where little things
start biting me in the behind, and I start spending inordinate amounts of
time hunting down little problems and finding things like objects which are
not hashes, but which are supposed to be, at the root of the problem.

I am very frustrated with these issues, and I'm definitely looking forward to
either something coming regarding interfaces or typing, either in Ruby or
Rite, or if another script language debuts that has it, giving that one a
solid try.

Sean O'Dell
 
S

Sean O'Dell

The objects are not always a Hash per se, just objects with hash-like
functionality. But, as I said, other objects can slip in too, like
strings
and arrays, which have [] and []= methods, but which don't act like
hashes at
all.

What gives them this hash-like functionality? Can you test for it? And
why would invalid objects be passed in?

It's tough to explain, the code affecting this is spread out in different
places. The code comes in as a tree, sort of like YAML. Actually, sometimes
it IS YAML, but sometimes it's just a tree of data (hashes, arrays, string,
other objects) that comes piped in from other scripts (my code is the server,
the other scripts are clients). The server needs certain points in the code
to be hashes, that is, to contain other objects and index them using other
objects, string, etc. Usually they're hashes, but sometimes they're these
other objects which I wrote that have hash-like functionality.

The only thing I know to test for using just built-in Ruby is [] and []=.
Unfortunately, if data comes in sport goofy, I get strings, arrays and others
things in the wrong places, and they sometimes also have [] and []=, so I
can't id them that way.

One test I can to really solve this problem is to create artificial tags for
Hashes, my objects and any other objects that get created either by me or
someone else as Hashes. That solution will work, but my complaint is that it
feels like such a kludge. My problem is solved though -- I have several
choices now. I just wish Ruby did this already. I am getting bit by little
stupid things that are hard to catch, and my growing project is now starting
to feel REALLY unstable. I never get that feeling with C++, so I guess I
should stop trying to use Ruby for these larger projects. This one though,
it started so nicely and fast...but now, it feels sort of kludgy and I don't
have a feeling of confidence about its ability to either perform properly, or
at least report errors that I consider errors. Since there is no typing
mechanism at all, I can't tell Ruby "hey, anything but a hash-like object
here is an error."

It's just frustrating now, that's all.

Sean O'Dell
 
G

George Ogata

Sean O'Dell said:
That's just a confidence issue. I don't care if the object coming in is
broken. I'm not concerned about catching objects which are implemented
improperly; that's actually very rare. If an object had a signature that
said "I am a hash-like object" that would be fine for me.

So if throughout the standard library, all "Hash-like" objects would
implement a #hashlike? method, that would be fine? It seems
unreasonable to me to expect that everything in the standard library
have a "X_like?" query method (or any other mechanism) for all
possible behaviours X. No matter what, you'll probably at some point
run into a situation where you want just one more method-or-something
that says that this object has some other behaviour.

Some "tagging" mechanism (e.g., mixing in a module) seems logical and
necessary. Yes, you'd have to retrofit your scheme onto all the
existing classes that you decide implements this interface, but how
can you expect not to -- you want to declare that classes implement an
interface that didn't exist when the classes were first written.
Duck typing and checking respond_to? are completely inadequate, and
it seems like people argue those points because Ruby offers nothing
else and so what are you going to advocate? It's those two or
rolling your own interface identification system, which I think is
cheesy; that sort of functionality should come from the framework.

Sorry for being slow, but I have no idea what you're after. Could you
give an example of what you'd like to be able to write to achieve what
you want?
 
J

Jeff Mitchell

--- Sean O'Dell said:
This is even worse than object.kind_of(Hash). The whole point of "duck
typing" (as I understand it) is that you don't check if an object has
certain methods. You just use them. Ruby will throw an error if there's
a problem.

Which always sounded fine to me until I was actually exposed to this kind of
"typing." The problem is, the methods [] and []= are there, they just don't
do what I need them to do. Duck typing completely and utterly don't help,
and Ruby has no way to tell me when an object's [] and []= are hash-like or
something else. My solution is going to end being something like "tagging
all objects that I know in advance to be hash-like, and then looking for that
tag at that particular point in my code." That's a kludge to me.

Why should you expect [] to imply hash-like behavior in the first place? It's
just a convenience method. What was the problem with the #lookup and #store
suggestion at [ruby-talk:102505]?

Honestly I don't see the issue here. The criteria you've chosen for a duck
is: "makes a light sound while walking". Well, tons of animals do that.
You need distinct "QUACK"s. Those quacks are #store and #lookup.





__________________________________
Do you Yahoo!?
Friends. Fun. Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/
 
J

Jeff Mitchell

--- Jeff Mitchell said:
You need distinct "QUACK"s. Those quacks are #store and #lookup.

Oops, I meant #store and #fetch. Hash already implements these.
Array, for example, only implements #fetch.





__________________________________
Do you Yahoo!?
Friends. Fun. Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/
 
G

gabriele renzi

il Sun, 6 Jun 2004 17:10:57 +0900, Jeff Mitchell
Why should you expect [] to imply hash-like behavior in the first place? It's
just a convenience method. What was the problem with the #lookup and #store
suggestion at [ruby-talk:102505]?

I believe Sean is correct in saying that what he defines as hash-like
behaviour is usage of [] with arbitrary objects. S
uggesting fetch and store is ok, but for many things it does not work
(say, pstore does not seem to have #store and #lookup, yet it has
hash-like behaviour via [])

BTW I believe that having a tagged interface would not fit anyway:
Say the user of the method has to write:
obj.implements:)"Hash-like-[]") before foo(obj).

At this point I'd prefer to just ask him for proper fetch and store.
Just IMVHO.
 
J

Jeff Mitchell

--- gabriele renzi said:
il Sun, 6 Jun 2004 17:10:57 +0900, Jeff Mitchell
Why should you expect [] to imply hash-like behavior in the first place? It's
just a convenience method. What was the problem with the #lookup and #store
suggestion at [ruby-talk:102505]?

I believe Sean is correct in saying that what he defines as hash-like
behaviour is usage of [] with arbitrary objects. S
uggesting fetch and store is ok, but for many things it does not work
(say, pstore does not seem to have #store and #lookup, yet it has
hash-like behaviour via [])

This is the fault of PStore or of the lack of agreed-upon semantics
for classes with hash-like behavior. There should be a standard list
which includes the definition of such behavior. Here, I'll start the
list now:

hash-like: #fetch, #store
array-like: #at, #store

Any others? How about tree-like?

I want this list to be part of the ruby standard -- clearly
documented so that implementers know they should define #fetch
and #store for the hash-like classes they write. [] should
be viewed as convenience only.






__________________________________
Do you Yahoo!?
Friends. Fun. Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/
 
M

Mauricio Fernández

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 just doesn't.

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
 
G

gabriele renzi

il Sun, 6 Jun 2004 18:52:44 +0900, Jeff Mitchell
This is the fault of PStore or of the lack of agreed-upon semantics
for classes with hash-like behavior. There should be a standard list
which includes the definition of such behavior. Here, I'll start the
list now:

hash-like: #fetch, #store
array-like: #at, #store

Any others? How about tree-like?

I want this list to be part of the ruby standard -- clearly
documented so that implementers know they should define #fetch
and #store for the hash-like classes they write. [] should
be viewed as convenience only.

I may be wrong but what you're asking has been throw out many times.
It would be wonderful to have stuff like this for everything,
toghether with a possible mix-in.
We have, actually, many 'default quacks' like :read and :write for
IOs, :each for enumerables, and so on.

Maybe adding some more mix-ins would be fine for many people's need
(say, if a Map mixin existed, we could have it rely on fetch(),keys()
and store() to provide all the other methods). This way hash-like
stuff like PStore, will just need to include the mix-in and Sean could
just check for kind_of? Map if he feels the need for this.

Oh, and can I ask for an Input and Output mixin, while I'm at it ? :)
 
D

David Garamond

Sean O'Dell wrote:
[snip]
at least report errors that I consider errors. Since there is no typing
mechanism at all,

You probably meant 'type checking' instead of 'typing'.
 
D

David Garamond

Sean said:
That's just a confidence issue. I don't care if the object coming in is
broken. I'm not concerned about catching objects which are implemented
improperly; that's actually very rare. If an object had a signature that
said "I am a hash-like object" that would be fine for me. Duck typing and
checking respond_to? are completely inadequate, and it seems like people
argue those points because Ruby offers nothing else and so what are you going
to advocate? It's those two or rolling your own interface identification
system, which I think is cheesy; that sort of functionality should come from
the framework.

Okay, I'm trying to sum up this thread as well as test whether my
understanding of this whole typing issue in Ruby is more or less correct.

---

1. Ruby _has_ types. It's called classes. In fact, all OO languages
which have a class concept (as opposed to some classless OO languages
like Self, I think) implement types through classes. All object belong
to a certain class. That class is the object's type.

2. However, Ruby does _not_ do type checking for you. This means, method
declaration is not like this:

def meth(a -> Hash, b -> Array); ...; end

Instead it's only like this:

def meth(a, b); ...; end

And if you want to do type checking, you'll have to code it yourself:

def meth(a, b)
raise ArgumentError unless a.class == Hash
raise ArgumentError unless b.class == Array
...
end

3. Ruby also does not tag a variable with type. This means, you don't
declare variable's type like this:

var a -> Hash
var b = Array

Instead, you just assign a value to a variable:

a = {}
b = []

and you can change a variable's value (and thus type) anytime you want
by reassigning it.

#2 and #3 are perhaps what people miss when they move from C++/Java to
Python/Ruby. I don't know whether Ruby will ever have #2 and #3.

4. Static type checking (or static typing?) is #2 and #3, done at
compile time. This is what C++ and Java do. Ruby, of course, does not
have type checking, much less static type checking.

5. "Duck typing" is basically no typing at all. Due to #2 and #3, we can
just pass around any kind of value (object) to any method, and the
method will just use that object as it wants. If the method needs to get
something out of the object (i.e. "make it quack") then the method will
just try to do 'obj.quack'. If the object fails to quack, then it's not
the right kind of object.

6. Object#respond_to? is not really related to typing (as in #2 and #3).
Its primary usage is to avoid 'obj.quack' to raise NoMethodError, i.e.
by checking first whether obj has a quack method.

7. Aside from classes as types, some OO languages (like Java and Perl 6)
also have interfaces/protocols as another sort of type checking. Ruby
does not have it, and I don't know whether it ever will. The choice is
currently to implement your own interface mechanism. Probably by
creating an Interface class and its subclasses (and thus creating the
interface hierarchy) and then tagging objects with these interfaces,
e.g. adding an 'implements' method to an object which will return a list
of interface classes that object implements.

---

So to do type checking, either:

a) use classes, and use Object#kind_of? and Object#class for type
checking (as in #2).

b) implement an interface mechanism (as in #7).

Sean seems to choose b), but reading the other posts, he also seems to
be able to control the generation of the incoming objects. Then why not
consider a) too? Instead of saying "hey, anything but a hash-like object
here is an error" then why not require every incoming object to be a
subclass of Hash and say, "raise ArgumentError unless obj.kind_of?
Hash". Ruby allows an object (like an empty hash) to be extended with
methods, so you can easily wrap object inside a hash and still be able
to do type checking with the simple kind_of?(Hash).
 
R

Robert Klemme

gabriele renzi said:
il Sun, 6 Jun 2004 18:52:44 +0900, Jeff Mitchell
This is the fault of PStore or of the lack of agreed-upon semantics
for classes with hash-like behavior. There should be a standard list
which includes the definition of such behavior. Here, I'll start the
list now:

hash-like: #fetch, #store
array-like: #at, #store

Any others? How about tree-like?

I want this list to be part of the ruby standard -- clearly
documented so that implementers know they should define #fetch
and #store for the hash-like classes they write. [] should
be viewed as convenience only.

I may be wrong but what you're asking has been throw out many times.
It would be wonderful to have stuff like this for everything,
toghether with a possible mix-in.
We have, actually, many 'default quacks' like :read and :write for
IOs, :each for enumerables, and so on.

Maybe adding some more mix-ins would be fine for many people's need
(say, if a Map mixin existed, we could have it rely on fetch(),keys()
and store() to provide all the other methods). This way hash-like
stuff like PStore, will just need to include the mix-in and Sean could
just check for kind_of? Map if he feels the need for this.

Oh, and can I ask for an Input and Output mixin, while I'm at it ? :)

Just a note: excessive need for type checks like these may be a hint for
weak OO design.

Kind regards

robert
 
K

Kent Dahl

Nathan said:
How about using the fetch and store methods? These work the same as
Hash#[] and Hash#[]=, but are unique to Hash.

ObjectSpace.each_object(Module){|m| p m if m.instance_methods.include?
"fetch" }

Both Hash and Array have fetch, apparently only Hash has store.

For other potentially unique candidates:

--------------&<--------------
target = Hash
methods = target.instance_methods

classes = []
ObjectSpace.each_object(Module){|c| classes << c }
classes.delete target

classes.each{|c| methods -= c.instance_methods }
puts methods.size, methods

=begin
$ ruby unique_interface.rb
15
value?
to_hash
merge!
merge
store
default
default=
default_proc
invert
has_key?
each_value
update
has_value?
rehash
each_key
=end
--------------&<--------------
 
J

Jeff Mitchell

--- Robert Klemme said:
gabriele renzi said:
il Sun, 6 Jun 2004 18:52:44 +0900, Jeff Mitchell
This is the fault of PStore or of the lack of agreed-upon semantics
for classes with hash-like behavior. There should be a standard list
which includes the definition of such behavior. Here, I'll start the
list now:

hash-like: #fetch, #store
array-like: #at, #store

Any others? How about tree-like?

I want this list to be part of the ruby standard -- clearly
documented so that implementers know they should define #fetch
and #store for the hash-like classes they write. [] should
be viewed as convenience only.

I may be wrong but what you're asking has been throw out many times.
It would be wonderful to have stuff like this for everything,
toghether with a possible mix-in.
We have, actually, many 'default quacks' like :read and :write for
IOs, :each for enumerables, and so on.

Maybe adding some more mix-ins would be fine for many people's need
(say, if a Map mixin existed, we could have it rely on fetch(),keys()
and store() to provide all the other methods). This way hash-like
stuff like PStore, will just need to include the mix-in and Sean could
just check for kind_of? Map if he feels the need for this.

Oh, and can I ask for an Input and Output mixin, while I'm at it ? :)

Just a note: excessive need for type checks like these may be a hint for
weak OO design.

It is not necessary to introduce a Map mixin, nor would I even suggest it.

I would certainly not advocate checking kind_of? Map. Instead, one blindly
calls #fetch and #store and then relies on ruby to raise an exception when
a method doesn't exist.

This is nothing new; nobody says kind_of? Enumerable (I hope) -- we just
call #each and see what happens.

I would prefer to stick with "hash-like" and leave it at that. The above
list I proposed has nothing to do with OO design per se, just convention
about what consitutes "hash-like" (and is NOT tied to a particular mixin,
necessarily).






__________________________________
Do you Yahoo!?
Friends. Fun. Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,144
Latest member
KetoBaseReviews
Top