On 4/2/06, Austin Z. [email protected] wrote:
:special_method)
return true if var.respond_to? :custom_array_method
def foo(arg1 : type_check)
def bar(arg1, arg2 : type_check)
I quite agree, showes my how helpless I braught this up. Should
have named the thread “Easier ways to enforce contracts”. Is that not
strange that we think types immediately and than are afraid of ancient
Computer Science History.
In Ruby, at least, inheritance is not a guarantee of a contract (even on
objects derived from core classes).
That is a very delicate point too, I strongly feel that a developper
should
know what kind of protocol an object is implementing and should be
able to
enforce this at a given point.
By extending core classes (and I love to do it BTW) she is taking great
risks.
If you do not agree, that means to me that you are probably a very very
talented designer, but do you not know error prone people like me?
It’s far better to think in terms of
what an object must do in your method, rather than to try to consider
what they are in your method. An example might help.
Transaction::Simple has a debug mechanism. It expects an object that can
respond to #<< for output (and I believe checks for it). By default,
that means that I support String, Array, IO (and most, if not all,
descendants), and StringIO. I explicitly wanted it this way, whereas if
I had placed a class check (and make no mistake: most people are
familiar with statically typed languages and the addition of this will
make people think of Ruby in terms of static typing),
might be and the way I presented it, for sure, real big mistake of mine.
I would have
prevented the use of all but the class(es) that I explicitly specified.
So you would not, why should you? There is no static typing, there is
only
the possibility of early renforcement of contract.
It might be a bad idea anyway, but I did not reach you. This is
completely
clear from your very elaborate answer, which I appreciate.
Look at it like this when we ask to check for certain conditions at
certain
points by means of assertions we have normally good reason to do so,
right???
I belive that the moment when a message is sent is often the ideal
moment to
reinforce such constraints.
def foo(x : {|para| %r{Robert is a real egghead} =~ x})
I can of course write that on my own in the next line, but it would just
be
against my laziness
Maybe it is a feeling that I need help for my shortcomings as a
programmer.
I thaught “contract enforcing mechanisms” might allow for an easier way
to
program defensively.
But I might be caught in too old paradigms, I really feel that you feel
this
way and I will take it quite seriously.
Unless you have a damn good reason to restrict a method to a
particular class, you shouldn’t be doing any sort of checking at all
that way. Checking on method presence (e.g., #respond_to?) is more
useful (but only partially so; you should check the #arity of a method),
but even that fails if the person forgets to implement #respond_to? when
they’ve implemented #method_missing. It’s also an extra run-time check
that, well, Ruby already does for you.
Meta programming might ruin it, singleton methods might ruin it, we
should
use only final classes and methods as in Java
Now you see I understand this, your reaction, it might be a very sound
one.
Make no mistake: I’m not afraid of static typing. I just think that it’s
useless in the context of real software development.
Agreed
I’ve been
developing software for … a long time. Professionally a little less
than that. I really cannot think of a time when I found that static
typing did anything except get in my way.
And you never used assertions neither as you stated above?
one reason I’m so consistently opposed to the Eater Nil that is
periodically proposed: it changes the behaviour to silently fail instead
of noisily fail if I get something I’m not supposed to (usually a nil;
in the stuff that I’ve developed, you won’t typically get a Real Object
that doesn’t work).
I take this point at 100%, I might be biased by bad design methods.
the opportunity.
It’s exceedingly ugly. It’s also no better, in implementation terms,
than placing the contract enforcement as lines of code at the top of the
method. Except that the latter is clearer, explicit, and infinitely more
maintainable than writing a miniprogram in the parameter list. (And can
easily be extracted to a unit test where that sort of thing probably
belongs in most Ruby code.)
Well I can live with this statement, I was quite aggressive too
Don’t get me wrong: there are times when specifying a type is necessary.
complex validation, which really does underscore my point that this
behaviour belongs in the method itself. Maybe we can have precondition
and postcondition sections of methods, but putting all this in the
parameter list is ugly and nonsensical.)
Well no, that was not intended , please remember that I never wanted
any
obligation to check.
I wanted a tool, and probably it is not useful, you quite convinced me.
I really fail to see why this is inhibiting the language. Such
programs fail explicitly and early, which is better (I claim) than
maybe failing later or just not behaving as expected.
Ah. That’s where you’re wrong: such programs would not fail any earlier
than they do now. The singular “advantage” to statically typed languages
is that they fail during the compile stage if there’s a mismatch. Your
method still won’t fail until it is called.
That was intened like this, it would fail when called and not maybe
three
stack levels later, but as you said already, I can enforce the contract
myself on crucial points.
-austin
–
Austin Z. * [email protected]
* Alternate: [email protected]
Thanks a lot for your precious time taken.
Robert
–
Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.