ruby static typing

C

caleb clausen

Some time ago, I wrote up some ideas I had for a comprehensive static
typing system for ruby. I never quite finished it all, but I'd appreciate
it if people can look it over as it is. I'd like to clean it up and put it
in an RCR (or three).

Looking back now, I see that everything is in there (tho the section on
polyparametric polymorphism could be expanded), except generic types (aka
templates) and the type conversion framework. I'll followup to this thread
with a short write-up on those when I can.

Anyway, here it is. It's kind of long, so I didn't post it to the
newsgroup, but just left it on wiki:

http://www.rubygarden.org/ruby?FlexibleRubyTypes
 
C

Charles Mills

caleb said:
Some time ago, I wrote up some ideas I had for a comprehensive static
typing system for ruby. I never quite finished it all, but I'd appreciate
it if people can look it over as it is. I'd like to clean it up and put it
in an RCR (or three).

Looking back now, I see that everything is in there (tho the section on
polyparametric polymorphism could be expanded), except generic types (aka
templates) and the type conversion framework. I'll followup to this thread
with a short write-up on those when I can.

Anyway, here it is. It's kind of long, so I didn't post it to the
newsgroup, but just left it on wiki:

http://www.rubygarden.org/ruby?FlexibleRubyTypes

Static typing is proposed very often on the mailing list and usually
doesn't get very far (for good reason IMHO).

Ruby does allow you to write statically typed code as is - via a C
extension.

-Charlie
 
D

David A. Black

Hi --

Some time ago, I wrote up some ideas I had for a comprehensive static
typing system for ruby. I never quite finished it all, but I'd appreciate
it if people can look it over as it is. I'd like to clean it up and put it
in an RCR (or three).

Looking back now, I see that everything is in there (tho the section on
polyparametric polymorphism could be expanded), except generic types (aka
templates) and the type conversion framework. I'll followup to this thread
with a short write-up on those when I can.

Anyway, here it is. It's kind of long, so I didn't post it to the
newsgroup, but just left it on wiki:

http://www.rubygarden.org/ruby?FlexibleRubyTypes

Please look at: http://www.rcrchive.net/rejected.html#rcr120. The
title of the RCR is, "Should Ruby have static typing?" Under "reason
for rejection", Matz wrote, "No, it should not."

The link also has other comments, as well as links to other
discussions (though there have been many more here on ruby-talk since
then).


David
 
L

Lyndon Samson

The link also has other comments, as well as links to other
discussions (though there have been many more here on ruby-talk since
then).

It would be nice to have a statically typed Interface of some sort
though, just to have something publishable, enforceable and easy for
tools to analyse.
 
D

David A. Black

Hi --

It would be nice to have a statically typed Interface of some sort
though, just to have something publishable, enforceable and easy for
tools to analyse.

I question whether a tool can analyze the capabilities of an object
whose capabilities are subject to runtime-only changes. To the extent
that the tool checks for class/module membership and ancestry (as
opposed to type), you're only getting the illusion of "type" and
therefore the illusion of type safety. That kind of check also
discourages duck typing (of which it is essentially the opposite) and
generally operates to constrain Ruby programs to a model and set of
programming habits for which the language does not, by design, provide
very much support.

As Matz once put it (in response to another RCR about static typing):

Ruby IS dynamic language. What you propose is to introduce static
typing into Ruby which violates the whole idea of Ruby Way. Please,
understand that class declaration has nothing to do with interfaces
or with idea of types. Class is just a convenient place to place your
your method declarations. An object can be changed dramatically during
its lifetime and the type of the object is determined only by methods
it responds to in any particular period of time.

One can of course ask an object what it responds to, before sending it
a message. That's a better fit, as a Ruby type-checking technique,
than class/module name-checking. It is not the same as duck typing,
though it's more in the same family of techniques. As I said in
another recent post, I personally tend to view respond_to? a kind of
"weak" duck typing: duck typing, in the sense that it deals directly
with the object's type and not with its class/module ancestry; "weak",
in the sense that it splits apart the checking for a behavior and the
requesting that behavior.

Quick Q&A, so that we don't have to go through them one by one :)

Q: Isn't changing an object's behavior dynamically bad practice?
A: No. That's what #extend is for, and that's why adding a method
to an object is as easy as: "def obj.meth; end" The idea that
this is bad is based on considerations extrinsic to Ruby.

Q: Do that many objects *really* get changed so that their classes
don't match their type any more?
A: Some -- and it's always possible, and it's a technique people
should be free to explore (since it's the basis of the design
of Ruby).

Q: Isn't Matz talking about adding some kind of
type-checking/filtering functionality to Ruby 2.0?
A: Yes. As far as I know it's still at the very broad conceptual
stage. Presumably it won't be a classname checking system :)


David
 
L

Lyndon Samson

Thanks for the dense ( in a good way :) ) response.

I guess my point is there is alot of mistrust in the 'corporate' world
as to whether dynamic/scripty languages are suitable for million+ LOC
projects.

Type safety seems to be a big selling point at that scale, so being
able to 'componentise' chunks of ruby by limiting coupling to using
rigid interfaces might assuage some of that concern. Of course after
the code executes post interface all bets are off with mutable
classes/objects, allthough Object.freeze probably needs a bit of
publicity here.

thanks for your response!

cheers
lyndon
 
F

Florian Groß

Lyndon said:
I guess my point is there is alot of mistrust in the 'corporate' world
as to whether dynamic/scripty languages are suitable for million+ LOC
projects.

Type safety seems to be a big selling point at that scale, so being
able to 'componentise' chunks of ruby by limiting coupling to using
rigid interfaces might assuage some of that concern. Of course after
the code executes post interface all bets are off with mutable
classes/objects, allthough Object.freeze probably needs a bit of
publicity here.

It has been suggested before that the right way of doing interface
contracts in dynamic languages is to formalize them with unit tests --
that seems to work out quite well (RubyOnRails uses unit tests for
assuring that new database adapters basically work).

There is however still cases where unit tests can not replace
traditional typing -- as a simple example you might have a method that
behaves slightly different depending on whether its argument is
enumerable or not. There is more cases where handling types at run time
would be nice -- type adaption comes to mind: For example you might
write a method that expects something that understands a hash-like
interface (keys, fetch, store, delete) and let your users supply Arrays
and so on as well.

Of course you might argue that those cases don't appear to frequently in
Ruby code and that seems to be true, but it still might be useful to
have idiomatic solutions for them.

So, because of the fairly common requests for static typing in Ruby, the
explorations of the Python community and just generic interest I decided
to code some of this up. You can find the resulting (still quite
experimental) library at http://ruby-contract.rubyforge.org/

This library indeed combines unit testing with type checking and while
it lets you use instance-of checks (it is generally compatible with all
checks that can be used in case .. when statements) their use is
discouraged in favor of actual implementation testing. (Which is like
duck-typing, except that it does not only check names, but also behavior.)

Perhaps this will do what you want, but even if it doesn't: Ruby has not
had static typing so far and because of that it is a more productive
language IMHO. I'm not encouraging carelessly written code, but Ruby
just happens to have other preferred ways of ensuring code quality.
 
R

Robert Klemme

caleb clausen said:
Some time ago, I wrote up some ideas I had for a comprehensive static
typing system for ruby. I never quite finished it all, but I'd appreciate
it if people can look it over as it is. I'd like to clean it up and put it
in an RCR (or three).

Looking back now, I see that everything is in there (tho the section on
polyparametric polymorphism could be expanded), except generic types (aka
templates) and the type conversion framework. I'll followup to this thread
with a short write-up on those when I can.

Anyway, here it is. It's kind of long, so I didn't post it to the
newsgroup, but just left it on wiki:

http://www.rubygarden.org/ruby?FlexibleRubyTypes

Folks, please once and for all drop the idea of static typing in Ruby.
Thank you!

Cheers

robert
 
S

SER

I question whether a tool can analyze the capabilities of an object
whose capabilities are subject to runtime-only changes. To the
extent

This is a good question. I've often expressed my approval of strong
typing, although I'm a proponent of type inferrence, rather than the
more common proposals for adding typing syntax. However, as I've often
said, a system like this would be useful to generate warnings, not
errors. If there was a typing system in Ruby, I'd have it use type
inferrence, and it would be enabled only when the user ran "ruby -c" on
their sources. It would generate warnings like:

WARNING: foo.rb:15: diddle.parse
'diddle' originally defined in babble.rb:24 as an Array
foo.rb::boozle( diddle ) called from fang.rb:64

A clever implementation would print the sequence of method calls that
led to the type error:

TYPING WARNING: foo.rb:15: diddle.parse
'diddle' originated in babble.rb:24 as Array
babble.rb:24 -> geezer.rb::thang()
geezer.rb:18 -> homer.rb::fink()
home.rb:23 -> lala.rb::trixie()
lala.rb:84 -> foo.rb::boozle()

Aside from typos, this is the most common sort of error in *all* of my
Ruby applications. Through a series of method calls, an object that I
think answers to some method isn't the object that I think it is. I've
had code that passes all of the unit tests I can think to write, and
gets used for a week *before* an error of this type up. These are the
most common sleeper errors I encounter.

Again, in some Ruby programs where the objects have methods dynamically
added, you'd get false warnings. They're warnings; you look at them,
find out that they're false positives, and ignore them. If it really
annoys you, don't run the checker. It isn't unreasonable to assume
that, once you have the basic type inferrence system in place,
extending it to recognize simple cases of dynamic class/object
extension wouldn't be too difficult, and the number of false positives
would be reduced. But the main point is that we'd have an additional
tool for checking the code *before* deployment, rather than discovering
it when it is in production.

I think that people who are most afraid of strong typing are people who
were bitten by Ada, or C, or Java, or some other language where you
spend a lot of time declaring variables. They are, by and large,
people who've not had any experience with languages that have type
inferrence, like Haskell.

My standard caveat applies: type inferrence can be a tricky problem,
and requires tight coupling with the parse tree of the sourcecode. I
don't complain about not having it because I'm not willing to write it
myself, but I'm happy to voice my opinion when other people bring up
the topic :)

--- SER
 
K

Kero

Thanks for the dense ( in a good way :) ) response.

"static typing does not work when your types are not static"

Anonymous classes, remove/undef_method, method_missing (and eval to
hide things even further) are all so dynamic.

As another poster put it, Ruby has other ways to get quality code.
I guess my point is there is alot of mistrust in the 'corporate' world
as to whether dynamic/scripty languages are suitable for million+ LOC
projects.

As if (void*) in C is a solution.
Adding a label doesn't fix things. In Ruby everything is an Object, that
should be enough for corporate drones.

As if Software Engineering in general is such a big success that it has
been proven that static typing is a panacea.
*cough* no silver bullet *cough*

The whole question about million+ LOC doesn't even make sense.
Use a language with e.g. S-expressions when you need to prove code.
Use a language that can be (and is) optimised when you need to crunch
numbers (perhaps on a massively parallel machine)
Use Ruby when you need flexibility.
[insert a few more demanding requirements and solutions/languages]
and then use Ruby for everything else :p
Type safety seems to be a big selling point at that scale, so being
able to 'componentise' chunks of ruby by limiting coupling to using
rigid interfaces might assuage some of that concern. Of course after
the code executes post interface all bets are off with mutable
classes/objects, allthough Object.freeze probably needs a bit of
publicity here.

Could you use a $SAFE level for that?


+--- Kero ----------------------- kero@chello@nl ---+
| all the meaningless and empty words I spoke |
| Promises -- The Cranberries |
+--- M38c --- http://httpd.chello.nl/k.vangelder ---+
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top