

Enforcing Type Returns in Ruby with Pedant - 0x44
http://superjared.com/entry/introducing-pedant-ruby-library-will-annoy-you/

======
gnaritas
If you want strong type guarantees, don't use a dynamic language. If you're
able to not make such silly mistakes and enjoy the power and expression of a
dynamic language, then use them, you won't miss types much at all.

I use Smalltalk daily and such type errors are so rare as to be virtually non
existent. If you pay attention to what you're writing, you don't make such
silly mistakes often, and when you do you usually notice it immediately when
you try to use the code you just wrote.

Bolting a home-brew type system on a dynamic language just seems rather
pointless, if you need it, you're not really ready to be using a dynamic
language.

~~~
antonovka
I find the inference that you must be a dolt ("If you're able to not make such
silly mistakes ...") to want an type system to be both insulting and
positively ridiculous.

A powerful type-system provides tools to _concisely_ express business/logic
constraints and automatically enforce those constraints across the entirety of
your codebase.

Advanced type systems are a powerful tool to enable you to write less code
that is guaranteed correct. It's not a seat belt for morons like myself who
apparently lack your mental caliber.

~~~
jballanc
I don't think the implication was that you "must be a dolt" if you feel the
need for a type system, just that you probably shouldn't be writing in Ruby. I
don't expect C to handle memory for me, I don't expect Java to interface
cleanly with the underlying OS, and I don't expect Ruby to enforce type
declarations.

I think the point is that, if you feel like you're missing something by not
having types enforced in Ruby, then you're probably using the wrong tool for
the job. Sure, I could probably turn a claw hammer around and use the nail-
puller to turn a screw in a pinch, but I'm not going to run a carpentry
business like that.

~~~
antonovka
The implication is pretty clear:

    
    
      If you're **able to not make such silly mistakes** and
      enjoy the power and expression of a dynamic language,
      then use them, you won't miss types much at all.
    
      If you **pay attention to what you're writing**, you
      don't make such silly mistakes often.
    
      Bolting a home-brew type system on a dynamic language
      just seems rather pointless, if you need it, **you're not
      really ready to be using a dynamic language.**
    

As an intelligent software engineer I do pay attention to the code that I
write and have come to the conclusion that advanced type systems, as a tool
for writing concise and correct code, provides me with an overall win.

Your mileage may vary.

That said, I'd be very willing to bet that a Ruby type checker/static analyzer
will find bugs (some of them serious) in your codebase, despite pervasive unit
tests. That has certainly been my experience with Python+pylint, and
Erlang+dialyzer.

~~~
gnaritas
No offense was meant though I see how you could take it that way. The
difference lies in what type system we're talking about. You're talking about
powerful type systems, I'm talking about most type systems.

The kinds of mistakes a Java'ish type system prevents you from making are
fairly trivial; we're not talking about Haskell here where type system can
actually encode most of the biz rules. The home brew system being bolted onto
Ruby here is not a powerful type system, it only prevents trivial mistakes
that are easily avoided by most who like and use dynamic languages to begin
with.

Static type advocates are always telling us about all the mistakes their type
systems prevent, and then go on to describe scenario after scenario that we
just don't actually run into. They're solving problems that really just aren't
problems for us. They seem to really believe you can't write a correct program
without such a system, but experience tells me otherwise because I do it all
the time.

I'm not against static typing, I'm against thinking it's the only approach
that works; it isn't. When I said _you're not ready to be using a dynamic
language_ I wasn't implying they're better, only that your mindset wasn't
ready, it's a different style of programming and you can't do it thinking
about types all the time. If a type system seems important to someone, they
shouldn't be using a dynamic language in the first place and trying to _fix
it_.

There are things I do in Smalltalk that I simply wouldn't or couldn't attempt
in C# and I have to adjust my programming style when switching between the
two. However, there are things I do in C# that I don't do in Smalltalk like
overloading that take advantage of the type system more.

Overall, I find the Smalltalk experience superior _for me_ because of things
like real meta-classes and #doesNotUnderstand: and the superior development
environment that simply let me get more work done with less and simpler code
and a runtime system that frees me from the compile/run/debug cycle.

------
FooBarWidget
I've been writing Ruby for years now and only a very tiny portion of my bugs
are caused by type errors. I don't see how this is useful in practice.

~~~
arohner
I've found similar systems to be very useful in certain situations, including:
refactoring, rapidly changing code bases, and code that doesn't have enough
unit tests.

Yes, all of these situations could be improved by having more unit tests, but
systems like these have an extremely high bang-buck ratio. They're extremely
cheap to put in, and they some bugs.

------
swombat
I'm not sure how useful this would really be in practice. It seems that it
would only be useful to debug obscure bugs if it was used consistently
everywhere. However, littering your code with these calls would make it a fair
bit more dirty, for a very small reduction in debugging time (apparently -
that's not event 100% clear... perhaps having to read all that extra code when
looking for a bug will make it take longer anyway).

I'll pass on this one, myself. Ruby's best used by people who have become
capable of not shooting their own feet without language safeguards.

~~~
kscaldef
There are situations where it's very useful. I've used similar modules for
code doing financial calculations. Because Ruby has weakly typed numerics,
it's quite easy to inadvertently coerce a value to Float. Once this happens
you will start seeing, as you say, obscure bugs from floating point errors.
The location where the bug manifests can be entirely different from the
location in the code where the type coercion occurred. Placing type
constraints on functions involved in these calculations seems quite warranted.

I wouldn't use this module on every function you write, and it doesn't seem
like the author is advocating that. But strategically enforcing the expected
types in critical portions of your codebase can be valuable.

~~~
blasdel
It would be 'weak' typing if Ruby ran an integer routine on a raw
mantissa|significand value. Ruby is effectively doing type-checks on every
operation, and that can _never_ be 'weak'

What you're complaining about is that it has a numeric tower, but does not
have anything like type-classes.

~~~
arohner
The problem is that ruby implicitly casts in a way that loses precision,
exactly the opposite of what the author (may) desire. Call it whatever you
want.

    
    
        2**100
        => 1267650600228229401496703205376
        > (2**100).class
        => Bignum
        > (2**100)*0.5
        => 6.33825300114115e+29
        > ((2**100)*0.5).class
        => Float

