Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Enforcing Type Returns in Ruby with Pedant (superjared.com)
13 points by 0x44 on Aug 25, 2009 | hide | past | favorite | 13 comments


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.


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.


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.


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.


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.


I would probably never use Pedant for a library that was never touched by other developers. Just like tests, Pedant can prevent others from breaking something (or at least bring attention to it). Ruby's implicit returns make this situation more apparent.


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.


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.


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.


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.


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.


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


No, I'm complaining that it has implicit type coercions, which is one flavor of weak typing.

(I suppose, I would also complain that it does implicit coercions in a way which results in loss of precision.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: