Ryan,

> You've got it backwards.  The core code should not have every possible
> pattern; this is silly.  It should provide the ones it uses and needs.
> Future classes, if they provide an interface that is useful to this
> code, they should document it by including the proper pattern.
>
> For example (let def_abstract define a method that raises
> SubclassResponsibility if unimplemented):
>
>     module Hashable
>         def_abstract :[], :[]=, :has_key?, :keys, :has_value?, :values
>     end
>
>     def show_hash(h)
>         expect h, Hashable
>
>         :
>     end
>
>     :
>
>     class SomeOddClass
>         include Hashable
>
>         def [](k);
>            :
>         end
>
>         :
>     end

An intriguing argument. By far the best that I have heard for Strong Typing.

I do wonder: what is really gained by Strong Typing? Are better error
messages the only advantage? An experienced ruby programmer will see a
method-not-defined error message and know that it means the wrong object was
probably passed in to his method. This kind of error message certainly
throws beginning Ruby programmers for a loop, but is it really a weakness of
the language?

If Strong Typing is an advantage how does it help experienced Ruby
programmers? Do you find that it saves a significant amount of time? Does it
help you catch errors you normally would not have known existed? Does it
encourage the right programming habits? If it can be demonstrated that it
does these things, perhaps it should be incorporated into the language.

I like the clean syntax, but I can't help feeling like I'm looking at code
someone with a strong background in statically typed languages would write.
How can you prevent someone from using Strong Typing in the wrong way? Is
there a way to accomplish this through a different implementation/syntax?

All Respect.
___________________
John Long
www.wiseheartdesign.com


----- Original Message -----
From: "Ryan Pavlik" <rpav / mephle.com>
To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
Sent: Thursday, November 06, 2003 12:50 PM
Subject: Re: Managing metadata about attribute types


> On Thu, 6 Nov 2003 21:57:15 +0900
> dblack / wobblini.net wrote:
>
> <snip>
> > > This is the fundamental philosophical disagreement, or
> > > miscommunication, or what have you.  If an object fits the bill, and
> > > its class/ancestry is wrong, then there is a error in design.
> > > It should not be the case that this happens, or you have found an
> > > error in your code.
> >
> > At this point you're waging a battle directly against the design of
> > Ruby.  Ruby allows you to extend objects at runtime; to decide that
> > this is sloppy or wrong or a second-rate programming technique is
> > entirely arbitrary.
>
> Not at all.  The fact you _can_ do something doesn't mean you must do
> it all over the place.  The fact you _can_ extend objects has no
> bearing on what the fact your class hierarchy documents the behavioral
> pattern well, either.
>
> > When you check whether or not an object's response to #is_a?  includes
> > an element you've specified, that's the one and only thing you're
> > checking.  It's not as if Ruby somehow pulls up its socks and
> > straightens its tie and says "Better stop this dynamic stuff!" when it
> > sees a call to #is_a?  It doesn't; it remains dynamic, and the
> > programming techniques required to ascertain the interface of an
> > object do not change.  (Besides, its socks and tie were just fine to
> > start with :-)
>
> You seem to have the preconception that #is_a? and "this dynamic
> stuff" are mutually exclusive in some way.  This is not the case.  The
> fact you're asking #is_a? just means you're asking if at some point it
> had a parent that was related to this class.
>
> I see this as both a fundamental problem of blindly using #to_*
> methods and a factor that has limited the perception of typing.
> When you call #to_f, or #to_s, you get a Float or a String... not a
> subclass.  (In fact, this is often used to work around having
> singleton strings, or not-quite-strings.)  Don't confuse this with
> actually _having_ a String subclass, which _is_ a String, but (likely)
> with some additional behavior.
>
> The primary goal of inheritence is dynamic extension.  The ability for
> you to add something later to the code and have it fall into the
> existing structure.
>
> Consider:
>
>    *  When writing code, you will never specifically want a type you
>       do not know about.
>
>    *  When using the code later, you can provide a specific subclass
>       unknown to the original code.
>
>    *  Thus, when type checking, you are not limited in any manner,
>       because you are asking for what you want (generally), and
>       getting it (specifically).
>
> Dynamicism doesn't fall out of the picture here at all.  (In fact, you
> could in theory construct ST expect() statements dynamically, although
> it would be odd.)
>
> > > I realize not all of Ruby is documented in this manner; that's a
> > > simple matter to change.  A few smaller modules would solve this; for
> > > instance, Set, HashedSet, IndexedSet, etc.  Array would be an
> > > IndexedSet; modules such as CGI would include HashedSet.  Then you
> > > could ask for the simple behavioral pattern you desire, and know that
> > > you have it.  You would further be assured that this #[] means what
> > > you want it to.
> >
> > I think I must be not getting something here; it sounds like you're
> > suggesting that every possible behavior of every future object in
> > every Ruby program be anticipated by modules in the core distribution,
> > with multi-barreled names to suit the purpose.  I'm thinking that
> > can't really be what you mean.
>
> You've got it backwards.  The core code should not have every possible
> pattern; this is silly.  It should provide the ones it uses and needs.
> Future classes, if they provide an interface that is useful to this
> code, they should document it by including the proper pattern.
>
> For example (let def_abstract define a method that raises
> SubclassResponsibility if unimplemented):
>
>     module Hashable
>         def_abstract :[], :[]=, :has_key?, :keys, :has_value?, :values
>     end
>
>     def show_hash(h)
>         expect h, Hashable
>
>         :
>     end
>
>     :
>
>     class SomeOddClass
>         include Hashable
>
>         def [](k);
>            :
>         end
>
>         :
>     end
>
> Now the code knows that SomeOddClass is, in fact, Hashable.  If you
> fail to implement one of the functions necessary, it will complain.
> This is only one example; you could make things a bit finer-grained.
> Perhaps have a HashAccessed that defines #[] and #[]=, and a subclass
> that defines the rest.  I am not sure that level of granularity is
> useful, but it is possible.
>
> > Also, remember that you're never 100% assured that #[] or any other
> > method means what you want it to.  It's ducks all the way down :-)
> > (http://www.the-funneled-web.com/hawking.htm) Every method call
> > operates under the same conditions as every other.  You can light a
> > candle, dance a jig, call #is_a? twenty times... but in the end,
> > obj#[] is whatever obj#[] is.  You can't change Ruby for a few
> > nanoseconds at a time through sheer willpower.
>
> This is only correct when blindly assuming that if #[] exists, it must
> act like you want.  Having the class/module tie gives you a semantic
> that further assures you it _does_ act like you want.
>
> This can, of course, be broken.  Many things can be broken in ruby
> though, but it is not desirable to do so.
>
> > Hence the quest to harness the dynamism, rather than wishfully think
> > that it comes and goes.
>
> There is no lack of dynamicism here.  Nor does type checking make the
> ability to extend classes on the fly go away or become less useful.
> I rely heavily on the strongtyping module in Mephle; I also do some
> modification to many base classes.  Just because something is a
> singleton, does not mean it's also not of the original class.
>
> <snip more type-checking-is-static-typing misconceptions>
>
> --
> Ryan Pavlik <rpav / mephle.com>
>
> "I have my rights. I want a fortitude check." - 8BT
>
>
>
>