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 Collingbourne

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

···

--
Posted via http://www.ruby-forum.com/\.

Hi --

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

···

On Sun, 27 Apr 2008, Joe K wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

Hi,

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

···

On Sun, Apr 27, 2008 at 5:50 AM, Joe K <jkauzlar@hotmail.com> wrote:

* Joe K <jkauzlar@hotmail.com> (21:46) schrieb:

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

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.

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

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.

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

On Mon, Apr 28, 2008 at 12:20 AM, Clifford Heath <no@spam.please.net> 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.

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

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.

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.

Hi --

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

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

···

On Thu, 1 May 2008, Joe K wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

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

···

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

Joe K wrote:

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.

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:

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.

···

On Thu, May 1, 2008 at 3:07 AM, Eric Hodel <drbrain@segment7.net> wrote:

On Apr 30, 2008, at 14:00 PM, Joe K wrote:
> 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

--
Rick DeNatale

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