On Apr 30, 2008, at 14:00 PM, Joe K wrote:
>> I think programmer sanity is probably helped by not having such a
>> `feature'. Reusing variables for different purposes is not at all  
>> what
>> [not] `typing' is about, and as David suggested, you possibly mean  
>> class,
>> not type. (singleton methods/whatever-you-want-to-call-them, for  
>> example?
>> are they part of the type? or something else?)
>>
>> The point of duck typing is that you don't need to/you shouldn't  
>> document
>> the 'types', seeing no purpose to restrict your definition of what's
>> considered valid input. Surely if the object responds in all the  
>> ways you
>> ask it to, it's fit for the task?
>
> Maybe I'm not in the correct mindset of dynamic programming. I've  
> always
> found it difficult to remember return values/parameter-types (i.e.  
> classes)
> for a large number of methods.

I find I have this problem less the more readable (as English) my code  
is.

Compare:

h = Hash.new 0

ARGF.each_line do |l|
   h[l] += 1
end

puts h.sort_by { |k,v| v }.first(10).map { |k,v| "#{v}\t#{k}" }

With:

counts = Hash.new 0

ARGF.each_line do |line|
   counts[line] += 1
end

top = counts.sort_by { |_, count| count }.first 10

puts top.map { |line, count| "#{count}\t#{line}" }

In the first example looking at any individual call or expression  
doesn't tell you anything about any of the surrounding code.  You have  
to trace back and follow types around to understand it.

In the second example, the types are objects.  If you look at just the  
last line, you can understand what I intend without reading any of the  
preceding lines.

Most of the expressiveness of the code sample above comes from Ruby's  
expressive and consistent core library, more so that choosing good  
names.  Unfortunately there are libraries that do not share the  
consistency of the core library.

> Don't get me wrong, I would much rather use
> Ruby at work than Java, but with a good IDE, Java's entire API is  
> available
> in pop-up windows AS YOU TYPE. While developing in ruby, I have  
> several
> rdoc's open in my web browser, files open in several terminal  
> windows, and
> an IRB session open, all for reference purposes when I'm working with
> unfamiliar APIs.

If an API is unfamiliar to me I'll use gem server or ri for hints, but  
once it becomes familiar I usually don't need it anymore.  If I always  
have to refer to API documentation, it's a sign of a poor API.

>> Surely if the object responds in all the ways you ask it to, it's  
>> fit for the task?
>
> Consider the common case of something like DataStructure#remove().  
> Does
> remove take an index or the object to be removed? Usually the API  
> developer
> supports one use case or another but not both. You should not have  
> to read
> the code to figure out which it is.

That API developer should be beaten with a stick.  Matz programmed my  
brain to expect this as the way to remove elements from a data  
structure by object:

$ ri Hash#delete
------------------------------------------------------------ Hash#delete
      hsh.delete(key)                   => value
$ ri Array#delete
----------------------------------------------------------- Array#delete
      array.delete(obj)            -> obj or nil

And this as the way to remove elements from a data structure by index:

$ ri Array#delete_at
-------------------------------------------------------- Array#delete_at
      array.delete_at(index)  -> obj or nil

I realize this was just an example, but APIs for third-party packages  
should exclusively follow the core library's examples.  This makes it  
easier for everyone to write code that they expect to work.

(When wrapping, say libxml, tk, etc., it is ok to exclusively follow  
the wrapped library's examples.  Mixing is always bad.)