# snip ...
EMPTY_STRING = %q
# snip ...
return EMPTY_STRING if options[:new_record]
return false unless (memoized_user = options[:user])
# more stuff with memoized_user ...
Do you see the problem? The first line within should_see_edit_link? should be
return false if options[:new_record]
My initial version was not a proper predicate, in that it did not restrict its returned values to only true or false. Bad coder. For what it's worth, the methods that use should_see_edit_link? themselves return EMPTY_STRING if should_see_edit_link? is truthy. Alas, not a good enough excuse.
This is exactly the sort of error that advocates of static typing mention as support for their preferred type system. The most experience I have with bondage & discipline typing is with Haskell, where I find it takes its proper place as part of a cohesive whole for understanding Haskell's approach to currying, implicit typing, the pointfree style, and so on. All of that is great, I just haven't found that static typing reduces the error rate in my code. In fact, it gets in my way more often than anything else. Maybe that's why I'm getting more into Erlang rather than Haskell. All of this is probably inseparable from the fact that I got into coding with dynamic languages.
The type error that prompted this blog post is atypical for me. I'm not claiming to write completely bug-free code, it's just that my errors tend not be the sort that can be caught by a static type checker. In fact, the only errors of this sort that I can remember making are this individual error and some others in Perl related to composite data structures being coerced into scalar context. The latter were more indicative of Perl's idiosyncratic (and in my opinion, failed) experiement with context than with dynamic typing as it's generally implemented outside of Perl. So I'm not sure that they count.
How about anyone else? Has static typing ever really saved your butt dramatically?
Caveat: Please don't interpret this post as going anywhere near addressing static typing as it relates to hardware optimizations during compile time. I'm just taking about human errors resembling the example.