On 4/2/06, Robert D. [email protected] wrote:
On 4/2/06, Austin Z. [email protected] wrote:
[…]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?
By and large, I don’t modify core classes except with modules, and in
libraries that I have released I try to make those modifications
separately loadable.
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.
Not just the way you’ve presented it. Pragmatic experience. A lot of
people are comfortable with the security blanket static typing and
they’ll see any parameter-level checking mechanism – especially one
that shorthands as you’ve suggested – as a way to get static typing in
Ruby.
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
But the block you’ve described is hard to read in the context of the
parameters (adding a lot of extra garbage in a parameter declaration is
really ugly and reduces readability). Maybe:
def foo(x) : { |x| %r{Another way} =~ x}
…
end
I donno, though. I still don’t like it and don’t think that it’s any
more useful than putting the assertion in the code. The only real
benefit would be if rdoc could be modified to detect such assertions,
and that could be done by convention:
def foo(x)
raise unless %r{Another way} =~ x # :precond:
…
end
Such things could then be added to documentation automatically.
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.
Enforcing contracts isn’t a bad thing. It’s just often important to
remember that Ruby does a lot of that enforcement for you and not
overthink it.
[…]
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?
I personally rarely use assert() in my C++ code; my coworkers use it a
bit more often, but my C++ is now strongly informed by my Ruby.
[…]
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
Part of what I like about Ruby is its aesthetics. I’m a little defensive
about things that I think reduce the aesthetics. (This includes a
proposal by Matz for Ruby 2.0 with the → mechanism as an alternative to
lambda.)
useful, you quite convinced me.
Actually, I wouldn’t be opposed to something like:
def foo(x)
precond do
# the precond must return a true value or an exception is raised
end
# implementation
postcond do
# the postcond must return a true value or an exception is raised
end
end
The thing is, that doesn’t require implementation in Ruby’s core or
changes to the syntax. But having something to do that formally in the
standard library might not be bad.
-austin