Typed ruby

I realize there is a holy war attached to this subject, but it would be
nice
to see a standard notation or library that would give ‘types’ to
variables
and methods, thereby potentially useful for IDE auto-completion; and
useful
for the sake of programmer sanity in general. Currently I document all
of
my methods and most of my variables with types, seeing no purpose to
re-using variables for different purposes

Is there an endeavor underway anywhere to provide a standard format for
this? If so, I’d like to use it. A quick google search brings up
nothing.

Joe K wrote:

I realize there is a holy war attached to this subject, but it would be
nice
to see a standard notation or library that would give ‘types’ to
variables
and methods, thereby potentially useful for IDE auto-completion; and
useful

We already do this in Ruby In Steel (see the IntelliSense section and
the part about ‘type assertions’ mid-way down this page:
http://www.sapphiresteel.com/Ruby-In-Steel-Developer-Overview ).

The way we do this currently is by allowing people to assert argument
types and return types in comment blocks. That means that they can gain
extra code-completion and parameter hint capabilities in the Ruby In
Steel IDE without in any way changing the meaning of the Ruby code
itself.

best wishes
Huw C.

SapphireSteel Software
Ruby and Rails In Visual Studio
http://www.sapphiresteel.com

Hi –

On Sun, 27 Apr 2008, Joe K wrote:

I realize there is a holy war attached to this subject, but it would be nice
to see a standard notation or library that would give ‘types’ to variables
and methods, thereby potentially useful for IDE auto-completion; and useful
for the sake of programmer sanity in general. Currently I document all of
my methods and most of my variables with types, seeing no purpose to
re-using variables for different purposes

Is there an endeavor underway anywhere to provide a standard format for
this? If so, I’d like to use it. A quick google search brings up nothing.

Reading between the lines, I suspect you mean class rather than type,
and it’s pretty easy to check objects for their class/module ancestry.
The problem is that Ruby objects have a life that’s independent of
their ancestry, so things like #is_a? don’t really cover the bases.

In general I wouldn’t worry too much about it. For whatever reason,
lots of Ruby programmers seem to be pretty sane :slight_smile:

David

Huw C. wrote:

We already do this in Ruby In Steel (see the IntelliSense section and
the part about ‘type assertions’ mid-way down this page:
http://www.sapphiresteel.com/Ruby-In-Steel-Developer-Overview ).

The way we do this currently is by allowing people to assert argument
types and return types in comment blocks. That means that they can gain
extra code-completion and parameter hint capabilities in the Ruby In
Steel IDE without in any way changing the meaning of the Ruby code
itself.

And does it also mean that if the comments are incorrect, the IDE gives
you the wrong answer? How do you test for that?

I think we should probably keep the holy war (Ruby vs. Ada for large
projects where large teams need to communicate, tools for such projects,
etc.) going, because I think it’s an important topic. Curiously enough,
a couple of years ago at a Scheme workshop, I heard some Schemers claim
that they “consistently” lost speed-coding contests to Java programmers,
all other things being equal, just because of Java’s typing mechanisms.
So …

Hi,

On Sun, Apr 27, 2008 at 5:50 AM, Joe K [email protected] wrote:

and useful for the sake of programmer sanity in general. Currently I
document all of
my methods and most of my variables with types, seeing no purpose to
re-using variables for different purposes

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?

Arlen

I realize there is a holy war attached to this subject, but it would be nice
to see a standard notation or library that would give ‘types’ to variables
and methods, thereby potentially useful for IDE auto-completion;

Could you elaborate on this potential usefulness for auto-completion?

mfg, simon … l

I think we should probably keep the holy war (Ruby vs. Ada for large
projects where large teams need to communicate, tools for such projects,
etc.) going, because I think it’s an important topic.

I think the Ruby vs Ada was ~more an interesting discussion than a “war”
:slight_smile:
But I agree, no matter how this is called anyway, it is interesting.

Joe K wrote:

Is there an endeavor underway anywhere to provide a standard format for
this?

Not that I know of, but you might find my “chattr” gem useful.

Arlen

Arlen,

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

Huw Collinbourne’s Visual Studio plug-in (link posted in this thread)
seems
to have a good, if not slightly cumbersome, notation for giving hints to
the IDE. I prefer a more compact Haskell-like notation (e.g. String *
Integer -> String), but at this point, any standard notation would be
useful.

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.

On Mon, Apr 28, 2008 at 12:20 AM, Clifford H. [email protected]
wrote:

Joe K wrote:

Is there an endeavor underway anywhere to provide a standard format for
this?

Not that I know of, but you might find my “chattr” gem useful.

Or, if you want to play with the ability to do complex yet structured
type declarations, Index of /~eivind/ruby/types/ -
this predates Gems.

Eivind.

Hi –

On Thu, 1 May 2008, Joe K wrote:

ask it to, it’s fit for the task?

Arlen

Arlen,

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)

Which do you mean: types, or classes? :slight_smile:

It’s not just an abstract distinction. Here’s an example. The ORM
library ActiveRecord allows for its instances to have collections of
other ActiveRecord objects. So you can do things like:

teacher.students

The object you get back identifies itself as an Array, when you ask
for its class. However, its interface is only partially like that of a
newly-minted Ruby array. In particular, #find is very differently
engineered.

So you really need to know how the object works, and the name of its
class doesn’t tell you. You need type information – that is,
information about what the object’s actual capabilities and behaviors
are.

Of course it’s possible (and people have done it) to decide up front
that it’s a bad practice to have objects that don’t behave like
newborn instances of their classes. But then you’re fighting Ruby. The
principle of extensible objects, and the principle of the separation
of class from type (or “nature” from “nurture”, in the object’s
life-cycle), is at the heart of Ruby.

That doesn’t mean you have to extend every object with a different
module. But it does mean that you’re limiting yourself a lot if you
decide that there’s something shady about objects that don’t behave
the way they did when they were born.

David

M. Edward (Ed) Borasky wrote:

And does it also mean that if the comments are incorrect, the IDE gives
you the wrong answer? How do you test for that?

Not as likely to happen as giving the wrong parameter type, IMO.

I think we should probably keep the holy war (Ruby vs. Ada for large
projects where large teams need to communicate, tools for such projects,
etc.) going, because I think it’s an important topic.

I’m not familiar with Ada, but I do believe Ruby could use work as a
large-project platform and not just a hacker’s language. I much prefer
Ruby
to most languages, but I’m tending to Scala now that it has the strength
of
the Java platform behind it without the mundaneness of the java
language.
Also, because its typing system is stronger than Java’s.

Curiously enough,
a couple of years ago at a Scheme workshop, I heard some Schemers claim
that they “consistently” lost speed-coding contests to Java programmers,
all other things being equal, just because of Java’s typing mechanisms.
So …

I have to use java at work and find I spend far less time actually
typing
code than with other languages. I tend to concentrate more on program
structure and design.

On Apr 30, 2008, at 14:00 PM, Joe K wrote:

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

On Thu, May 1, 2008 at 3:07 AM, Eric H. [email protected] wrote:

object:
$ ri Array#delete_at
-------------------------------------------------------- Array#delete_at
array.delete_at(index) → obj or nil

Truth be told, I think that this actually is evidence that delete
sometimes deletes by object, and sometimes by index, at least if you
think of keys as Hash indices

There are some other differences if you look at the full doc,
Array#delete will delete multiple occurences of the value, and will
return nil if there is no occurrence. Hash#delete can only delete one
think since it’s deleting by key and keys are unique, and Hash#delete
returns the default value for the hash if the key is not found. There
seems to be a doc bug in Hash#delete since it says that it returns the
key value pair, but it seems to return just the value.

If Hash#delete and Array#delete were really parallel then Hash#delete
would be something like:

class Hash
def delete(object)
default = nil if default == object
if has_value?(object)
delete_if {|key, value| value == object}
object
else
nil
end
end
end

Not that I’d argue for this change.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Joe K wrote:

So …

I have to use java at work and find I spend far less time actually typing
code than with other languages. I tend to concentrate more on program
structure and design.

Despite what many people say about it, Java is an exceptionally
well-designed language. I was amazed at how easy it was to write Java
code when I first tried it. I wrote one program, a queuing theory model.
It took me no longer to write it than it would have in, say, Perl. But
it never got used and it sits today in a CM repository. And I’ve never
written any Java since.

However, everything I say good about Java pertains only to the Sun
implementation. I wouldn’t touch the others with … well … anything.
:slight_smile: