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.)