How to duck type? - the psychology of static typing in Ruby

John Carter wrote:

Duck typing is an even freer form of polymorphism and in the case of the
example I mentioned, with Duck Typing, the geometry library would work
on anything that responded to +,-,*,/,==,<, including Vectors and
Matrices!

I’m hinting at a prime rule of polymorphic / duck typed design. Don’t
gratuitously constrain the interface. Reusable means you don’t know what
other types may be fed to you in future, and to be reusable you must
allow it.

This is a good guideline for basic types like numbers, strings, arrays,
etc., because people do tend to create or reuse “similar types” (e.g.
DBI::Row or whatever it is, instead of Hash) which should “just work” with
your library.

But as you move away from basic types, through to middle-ground types,
like an XML document representation, to domain types, like a customer, the
balance changes. The prime rule you mention above becomes less and less
important.

If I’m writing some sort of CRM library that I want to share with the
world and have reused, then I should obviously document my interface well,
and not be overly strict about what I accept. Even so, it’s very unlikely
that someone else is going to have a class they’re using that’s
similar-to-but-not-quite my OpenCRM::Customer class. The benefits of a
duck typing attitude are not likely to take root in this system. But I’m
creating a library that is aimed at reuse, so I should allow for reuse.

Now, one step further: an internal application that is never going to
leave company walls. A system (involving customers, invoices, and
payments, say) that is entirely self-contained, and not aimed at reuse at
all. In this case, my system is designed to work with XYZ::Customer
objects, XYZ::Invoice objects, and XYZ::Payment objects. Furthermore, I
may reasonably use some class-checking code at strategic points. This is
not because I feel unsafe without it; it’s to encode the practical
limitations of the software. A line like

expect(customer, XYZ::Customer, payment, XYZ::Payment)

is executable documentation. It reminds you at a glance what you’re
dealing with. It gives you some context, some knowledge to build on when
you’re editing that method after a few months away from it. And it’s
documentation that doesn’t go out of date. The fact is, I’m not
needlessly restricting the interface (in any practical sense) by including
the above line. The interface was already restricted because of the
special-purpose nature of the system. (That line is using the
‘strongtyping’ library, BTW.)

The reason I canvas these examples is to emphasise that isolation (i.e.
not planning for reusability) is not necessarily a software sin. I agree
with the spirit(s) of the duck-typing discussions, but don’t want some
impressionable lurker thinking “Hey, I’m not considering reuse; am I
overly restricting the interface?; am I using Ruby correctly?” etc.
There’s a spectrum of reusability, and the onus is on the programmer to
work out where they are aiming and to use the appropriate techniques.
That’s a blessing and a curse. In other languages, you’re forced to
handle all typing issues in a certain way, which is restrictive, but at
least you don’t have to think. Personally, I’d rather think.

There’s a time and place for everything in Ruby :slight_smile:

Cheers,
Gavin

“Marek Janukowicz” childNOSPAM@t17.ds.pwr.wroc.pl schrieb im Newsbeitrag
news:slrncai5v9.5f6.childNOSPAM@child.ha.pwr.wroc.pl…

Broken record time:

The problem with all of these solutions is that they are discovered at
run-time. I find it increasingly irritating when I have to debug
typing errors by running an application that takes some time to get to
the error. Enough of those times, the error is a typing error, so that
I’ve been harping lately about wanting a duck-type checker hooked in to
“ruby -c”.

I guess due to the nature of Ruby it’s impossible to check this without
actually executing the code because of Ruby’s dynamic typing.

If you want compile time type safety you need to use a statically typed
language. Both types of programming languages have their pros and
cons -
but you can’t get both at the same time.

What about Objective-C? It has static typing (with regular pointers) and
kind of dynamic typing (“id” type). Maybe Ruby should have similar
capability? Or maybe I just told something really stupid?

I alway have to look up definitions…

Unfortunately I’m not familiar with Objective C so I can’t judge on that.
From what I’ve seen so far I’d assume it’s similar to Java which is regarded
as statically typed although you have access to type information at runtime
(as seems to be the case with Objective C). But the crucial part is that
you declare types (of variables, of method arguments) in code and these
types are checked by the compiler.

Ruby does not do this (as does Lisp, although it seems there are some
optimization type hints). So without these declarations it’s difficult to
do type verification at compile time without code execution. To introduce
this wuold be a major change in the language and break lots of code. If you
would allow for typeless and typed method arguments at the same time, you
would increase interpreter complexity by orders of magnitude and code would
be a real mess. I don’t think, it’s a good idea.

Kind regards

robert
···

On Mon, 17 May 2004 16:50:19 +0200, Robert Klemme wrote:

“Gavin Sinclair” gsinclair@soyabean.com.au wrote…

[1] I’ve yet to read an example of unit testing that isn’t fairly
convoluted anyway - references, anyone?

The simplest example of unit testing I’ve seen (except for Tim’s contrived
example) is at the start of the Extreme Programming site’s Coffee Maker:
http://www.extremeprogramming.org/example/piacode.html

I’m careful to separate the application and business object code from
the UI side, making it easier to test. I also use a lot of
meta-programming, which cuts down on the amount of stuff where testing
is needed.

(I also have a dirty secret when it comes to unit testing, but I’m not
going to share it here… :))

Cheers

Dave

···

On May 19, 2004, at 9:48, Marek Janukowicz wrote:

OK, but I personally find it difficult to write unit tests for some
kind
of programs (especially web and GUI applications). I don’t see any
testing frameworks for such programs laying around. I really would like
to follow the path you presented above, but how can I do this without
being able to write tests? You said before you mostly write web
applications - could you share your experience regarding testing them
with us?

Sean Russell wrote:

I keep thinking that if I push the idea too hard, I’ll be tarred and
feathered.

Then your goose would be cooked

But may be the idea will take flight, if people don’t think it too fowl.

James

···

— SER

.

I’m posting a lot on this topic because I think we have people
approaching the issue from two different directions.

John Carter john.carter@tait.co.nz wrote in message news:Pine.LNX.4.58.0405181209490.28204@parore.tait.co.nz

The tighter you constrain the interface, the less reusable it is. In the
example I mentioned, the programmers had ruined the polymorphic behaviour
of the library by internally squashing everything into two byte int’s. If
they hadn’t done that, polymorphism would have allowed the library to work
on anything that inherited from Number. Including the floating point
types I needed.

Inferrence duck-type checking doesn’t constrain the interface
significantly.

Consider:

def meth( arg )
arg.each { |x| … }
end

Now, the type checker knows that arg must implement #each(), and
that each() should accept a closure, right? So if call this method
from somewhere else with:


othermeth( 2
meth( 5 )

the checker should be able to warn me that this is probably not going
to work. I’m imagining something like:

$ ruby -c myprog.rb
myprog.rb:53: syntax error
myprog.rb:54: ducktype warning: “5” does not implement each()

An important aspect is that “-c” would check all of the code, not just
the parts that are more commonly used. It will catch things that are
missed by unit tests. It will find potential errors in your program
before you go into production. It will cure cancer, clean the air,
and bring peace to the Middle East.

I don’t want to have to declare variables any more than anybody else;
what I want is a smarter “-c” code checker to find potential errors.

— SER

“Sean Russell” ser@germane-software.com schrieb im Newsbeitrag
news:83173408.0405191014.2ccbc591@posting.google.com

“Robert Klemme” bob.news@gmx.net wrote in message
news:2gs1pcF65u2uU1@uni-berlin.de

I guess due to the nature of Ruby it’s impossible to check this
without
actually executing the code because of Ruby’s dynamic typing.

If you want compile time type safety you need to use a statically
typed
language. Both types of programming languages have their pros and
cons -
but you can’t get both at the same time.

This isn’t strictly true.

The important thing to notice here is the difference between type
declarations and type inferrence. Few non-functional languages have
type inferrence, so most people who haven’t used functional languages
don’t realize that there is a difference.

My functional languages knowledge is a bit rusty nowadays, but would type
inferrence give us type safety in Ruby? After all (considering
overloading) there are enough situations where type inferrence would not
be able to come up with a completely typed signature.

Type inferrence relies not on type declarations, but on the compiler
(or run time system) to determine types based on how objects or data
is being used. Interpreters can also do type inferrence checking, and
there isn’t anything stopping Ruby from doing it, either. Keep in
mind that I’m not recommending that Ruby do inferrence type checking
all the time – just when the user calls Ruby with the “-c” argument.
I’ve also said numerous times that Ruby won’t be able to check all
types because of it’s self-modifyable nature, but it could probably
cover the majority of cases.

IMHO that’s the crucial point: given that certain method names (e.g.
“length”) and operators (e.g. “+”, “<<”) are used in a whole lot of
different contexts, is it really the majority of cases or rather a
minority? I’m sceptical that the effort to implement this really pays
off…

In fact, I’m of the opinion that type inferrence dove-tails nicely
with duck-typing. Of course, this idea may not fly with Matz; he’s
indicated that he thinks the idea is a bit of a turkey. Still, if we
had type inferrence, we could kill two birds with one stone: Ruby
would have a stronger, more “proveable” type system, and we’d satisfy
some of the strong typing proponents in the group. I don’t want to be
pigeon-holed as a feature-whiner, but I quail at the idea of
implementing this.

I keep thinking that if I push the idea too hard, I’ll be tarred and
feathered.

You’ll just get assigned the task to implement it. :slight_smile:

Regards

robert

John Carter wrote:

Duck typing is an even freer form of polymorphism and in the case of the
example I mentioned, with Duck Typing, the geometry library would work
on anything that responded to +,-,*,/,==,<, including Vectors and
Matrices!

I’m hinting at a prime rule of polymorphic / duck typed design. Don’t
gratuitously constrain the interface. Reusable means you don’t know what
other types may be fed to you in future, and to be reusable you must
allow it.

This is a good guideline for basic types like numbers, strings, arrays,
etc., because people do tend to create or reuse “similar types” (e.g.
DBI::Row or whatever it is, instead of Hash) which should “just work” with
your library.

But as you move away from basic types, through to middle-ground types,
like an XML document representation, to domain types, like a customer, the
balance changes. The prime rule you mention above becomes less and less
important.

Now, one step further: an internal application that is never going to
leave company walls. A system (involving customers, invoices, and
payments, say) that is entirely self-contained, and not aimed at reuse at
all. In this case, my system is designed to work with XYZ::Customer
objects, XYZ::Invoice objects, and XYZ::Payment objects.

Hmm. I never aim at reuse, I just don’t do anything that would
gratuitously prevent reuse in unexpected manners. Write code that
expects it’s output to be the input of some, as yet, unspecified
program.

Do you really need to work with XYZZY::Customer objects, or could your
interface be something much simpler? Perhaps a tuple of numbers? Hey!
Looky I have built graphical output into my program! How?! By making
my output something simple, (tuples instead of XYZZY::Customer) I can
feed it trivially into any graphics package like gnuplot.

If you write things made out of Big Balls of Mud, don’t be suprised
when the result glues it self up into an un-reusable Bigger Muddier Ball.

So invoicing passes a big hairy XYZZY::Customer object to Billing,
Billing only uses the name and address, shouldn’t you have weakened
the interface so you only pass a name and address to billing instead?

Furthermore, I may reasonably use some class-checking code at
strategic points.

So long as “.kind_of?” is just a short cut for a long list of “.respond_to?”'s

The reason I canvas these examples is to emphasise that isolation (i.e.
not planning for reusability) is not necessarily a software sin.

Never plan on being resuable.

Plan on being simple.

Plan on being seperable.

Plan on being generous on what you accept and rigorous on what you
deliver.

http://www.catb.org/~esr/writings/taoup/html/

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

The universe is absolutely plastered with the dashed lines exactly one
space long.

···

On Tue, 18 May 2004, Gavin Sinclair wrote:

Broken record time:

The problem with all of these solutions is that they are discovered at
run-time. I find it increasingly irritating when I have to debug
typing errors by running an application that takes some time to get to
the error. Enough of those times, the error is a typing error, so that
I’ve been harping lately about wanting a duck-type checker hooked in to
“ruby -c”.

I guess due to the nature of Ruby it’s impossible to check this without
actually executing the code because of Ruby’s dynamic typing.

If you want compile time type safety you need to use a statically typed
language. Both types of programming languages have their pros and
cons -
but you can’t get both at the same time.

What about Objective-C? It has static typing (with regular pointers) and
kind of dynamic typing (“id” type). Maybe Ruby should have similar
capability? Or maybe I just told something really stupid?

I alway have to look up definitions…
Type system - Wikipedia

Unfortunately I’m not familiar with Objective C so I can’t judge on that.

I cannot say I know Objective C well too, but I get some basic concepts.

From what I’ve seen so far I’d assume it’s similar to Java which is regarded
as statically typed although you have access to type information at runtime
(as seems to be the case with Objective C). But the crucial part is that
you declare types (of variables, of method arguments) in code and these
types are checked by the compiler.

But the feature I described in my previous post has no equivalent in
Java - I’ll try to explain it (I may be very wrong, so anyone knowing
Obj-C better please correct me):

In Obj-C, when you create a variable to hold a pointer to an object of
class Object, you have 2 choices:

Object *obj;
id obj;

the second pointer is “typeless”, because it can point to an object of
any class. I wonder if similar mechanism could be useful in Ruby.

Ruby does not do this (as does Lisp, although it seems there are some
optimization type hints). So without these declarations it’s difficult to
do type verification at compile time without code execution. To introduce
this wuold be a major change in the language and break lots of code. If you
would allow for typeless and typed method arguments at the same time, you
would increase interpreter complexity by orders of magnitude and code would
be a real mess. I don’t think, it’s a good idea.

I’ll try to explain my idea in more detail. I suggest that one could put
optional type information when declaring the variable, eg:

def some_method ( String str, second_param )

do |Array ar, smth, Fixnum int|

etc.

So basically, current typeless declaration would become something
similar to Obj-C’s id, and new typed one would be similar to Obj-C’s
Object*.

Note I don’t mean to change (dynamic) method dispatching here - I just
wish Ruby had some mechanism for type checking on variable assignment,
so I don’t get enigmatic error messages deep inside a library I use (but
I didn’t write). Of course such mechanism would not prevent some runtime
errors (given you can remove method from an object), but it would surely
be very useful (at least for me).

In other words, this feature would be equivalent of ‘strongtyping’
library, just with better syntax and compile-time checking (to avoid
runtime overhead).

···

On Tue, 18 May 2004 08:48:04 +0200, Robert Klemme wrote:


Marek Janukowicz

If I’m writing some sort of CRM library that I want to share with the
world and have reused, then I should obviously document my interface well,
and not be overly strict about what I accept. Even so, it’s very unlikely
that someone else is going to have a class they’re using that’s
similar-to-but-not-quite my OpenCRM::Customer class. The benefits of a
duck typing attitude are not likely to take root in this system. But I’m
creating a library that is aimed at reuse, so I should allow for reuse.

How about a delegator to your Customer class, with some extensions for
distributed computing?

That’s a very common one that can be gotten wrong: Will your type checks
work with a dRb proxied object?

Ari

What about Objective-C? It has static typing (with regular pointers) and
kind of dynamic typing (“id” type). Maybe Ruby should have similar
capability? Or maybe I just told something really stupid?

I alway have to look up definitions…
Type system - Wikipedia

Unfortunately I’m not familiar with Objective C so I can’t judge on that.
From what I’ve seen so far I’d assume it’s similar to Java which is regarded
as statically typed although you have access to type information at runtime
(as seems to be the case with Objective C). But the crucial part is that
you declare types (of variables, of method arguments) in code and these
types are checked by the compiler.

Well, ObjectiveC has the issue that it supports non-object types:
regular C integers, things like that, so it has to support static
typing, yes.

It also has the id type, which is “any object”. It also has typed
pointers to specific classes-or-descendants, too. It’s a rather hybrid
thing.

A large part of what sets ObjC apart from Java and C++ is that “id”
type: any object, and the isa pointer, the runtime type information, so
you can tell what the data is from a generic pointer.

C++ and Java, if you have a pointer to a Rect instance, will only let
you call methods defined in Rect or parents, unless you cast to a
subclass – and heaven help you if the instance wasn’t actually the
subclass.

In ObjectiveC, you can send any message to any object, and if it’s not
supported, it will call the unsupported selector method instead
(allowing dRb-like proxy objects). ObjectiveC is strongly and
dynamically typed (with a static check option), and C++ and Java are
weakly and statically typed.

Ruby is, of course, also strongly and dynamically typed. It also has no
primitive types like Java and C variants, so everything is an object.
That’s one reason static type checking isn’t needed: All instances have
the header that tells what type of object it is. There won’t be any
memory overrun errors when the runtime, say, tries to access the type
field of a C-style int.

Which leaves the program domain. Not checking the actual class lets one
write mocks, proxies and replacement classes. It makes one define, or
at least think about the interface, since it’s not coupled to a class. I
think that’s a good thing: If you write a program that can robustly deal
with anything that quacks like a duck, you’ve probably got a decent,
usable interface.

Regarding exceptions: There’s a maxim to crash early and loudly. That’s
a good thing. However, there’s places where actually checking the type
(or interface, even) and throwing an exception is a pretty minor detail:
Is an ArgumentError that much more descriptive than a NoMethodError?
Let the place that calls the code throw the exception, or let it be
thrown at the critical places, so you don’t scatter
exception-translating code (catching a NoMethodError and throwing an
ArgumentError in response) all over your code, at every accessor.

Instead, perhaps, apply the validation pattern and collect it in one set
of methods, checking for the purpose at hand. Write your code in small,
generic pieces, so that it’s obvious what sorts of objects will be in
each place. Write transparent code.

Ari

Let me tell you a little story…

Once upon a time I was stuck at work doing psychological support. It
was an Windows server and hence, ‘not my problem’, but the guy lived
near my place, so we usually walked home together, so I stuck around.

I figured I might as well do something semi-useful, and had been
irritated by the fact that internal documentation was these HTML files
stuck somewhere. I had an idea about these editable pages, so I
started fiddling with some PHP…

In a few hours I had something that worked, you could edit sections on
a page, add and delete pages, so on and so forth. Didn’t look to bad
on the outside, but the code wasn’t exactly what you’d call, ahem,
structured. It was a quick hack, and it worked.

I thought, “I’ll call this SiDoc”, from the initials of the company,
and proceeded to show it to my boss. He liked it, and it was quickly
decided that this was what we’d use for internal documentation. All
was nice.

A little while later, he came and asked if I could make a copy with a
‘view only’ version, so you’d have 2 pages, where only one could
edit. I said ‘sure’, made a copy and removed the edit links from one.

It wasn’t until a few days later that I discovered that my one day
hack was suddenly the CMS system for a site… Made me wish I’d
actually bothered to clean up the duplicate code.

That was a few years ago. SiDoc is still the internal documentation
system, even though the company has changed name and wikis has gained
popularity. And it’s still the CMS behind a site about small local
harbours.

I learned 2 things from this: Don’t clean up your code ‘later’, and
there’s no limit on how your code will get abused. Even by
yourself. :wink:

···

On Tue, May 18, 2004 at 11:04:35AM +0900, Gavin Sinclair wrote:

There’s a spectrum of reusability, and the onus is on the programmer to
work out where they are aiming and to use the appropriate techniques.


Thomas
beast@system-tnt.dk

Dave Thomas wrote:

(I also have a dirty secret when it comes to unit testing, but I’m not
going to share it here… :))

Where and when will the sharing be unveiled? :slight_smile:

···


Chris
http://clabs.org

James Britt wrote:

Sean Russell wrote:

I keep thinking that if I push the idea too hard, I’ll be tarred and
feathered.

Then your goose would be cooked

But may be the idea will take flight, if people don’t think it too fowl.

If you typed that, you’d better duck.

We’ll put it on your bill.

Hal

OK, but I personally find it difficult to write unit tests for some
kind of programs (especially web and GUI applications). I don’t see
any testing frameworks for such programs laying around. I really
would like to follow the path you presented above, but how can I do
this without being able to write tests? You said before you mostly
write web applications - could you share your experience regarding
testing them with us?
I’m careful to separate the application and business object code from
the UI side, making it easier to test.

Such a separation is rather obvious. The business logic is rather easy
to test, but in my experience most bugs occur on the UI side (especially
in the connection layer between UI and business logic). How do you test
UI?

I also use a lot of meta-programming, which cuts down on the amount of
stuff where testing is needed.

Could you elaborate some (maybe trivial) example? I know what
meta-programming is, but I don’t know how can it be employed in eg. web
application testing.

(I also have a dirty secret when it comes to unit testing, but I’m not
going to share it here… :))

That’s really a pity :slight_smile:

···

On Thu, 20 May 2004 03:43:22 +0900, Dave Thomas wrote:


Marek Janukowicz

You tease, you.

I think everyone has their dirty unit testing secrets. Somewhere, in
some corner of reality, there is the Platonic ideal test suite. All our
test suites are flawed reflections of that ideal. However, by aiming at
that perfect suite, we at least come closer than if our sights had been
set lower.

C

···

On 20/05/2004, at 4:43 AM, Dave Thomas wrote:

(I also have a dirty secret when it comes to unit testing, but I’m not
going to share it here… :))


Contributing to the heat death of the Universe since 1975
cmiller@pastiche.org http://fishbowl.pastiche.org

I’m posting a lot on this topic because I think we have people
approaching the issue from two different directions.

I like what you are saying, it is an excellent idea. In fact I like it
so much, because it is one of my own, (although we probably came to it
entirely independently).

My pet hobby over the last several years has been to design a postfix,
linear logic combination of Joy and Ruby that does exactly what you
are suggesting.

Inferrence duck-type checking doesn’t constrain the interface
significantly.

Consider:

def meth( arg )
arg.each { |x| … }
end

Now, the type checker knows that arg must implement #each(), and
that each() should accept a closure, right? So if call this method
from somewhere else with:

I immediately see two problems with implementation though…

a) Ruby is too dynamic, the value it is called with may well gain the
method between compilation and execution of that line. A case in
point is the ‘cgi’ module which won’t just break under your ruling, it will
shatter.

b) Ruby has a remarkbly “narrow” (local) view of the world as it
compiles, to implement your suggest it would require a more global
view, if not multiple passes. This “local” view is important, it
keeps Ruby simple and fast.

Perhaps your suggestion should be implemented as a standalone “lint”
rather than as part of Ruby.

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

The universe is absolutely plastered with the dashed lines exactly one
space long.

···

On Thu, 20 May 2004, Sean Russell wrote:

My functional languages knowledge is a bit rusty nowadays, but would type
inferrence give us type safety in Ruby? After all (considering
overloading) there are enough situations where type inferrence would not
be able to come up with a completely typed signature.

There’s some discussion of this in “Dynamic vs. Static Optimization
Techniques for Object-Oriented Languages” by Urs Hölzle & Ole Agesen.
Their static optimization technique is static type inference. I can’t
really remember the conclusions, except that they certainly didn’t
manage to infer all types.

– George

“Marek Janukowicz” childNOSPAM@t17.ds.pwr.wroc.pl schrieb im Newsbeitrag
news:slrncajk30.4g8.childNOSPAM@child.ha.pwr.wroc.pl…

Broken record time:

The problem with all of these solutions is that they are
discovered at
run-time. I find it increasingly irritating when I have to debug
typing errors by running an application that takes some time to
get to
the error. Enough of those times, the error is a typing error, so
that
I’ve been harping lately about wanting a duck-type checker hooked
in to
“ruby -c”.

I guess due to the nature of Ruby it’s impossible to check this
without
actually executing the code because of Ruby’s dynamic typing.

If you want compile time type safety you need to use a statically
typed
language. Both types of programming languages have their pros and
cons -
but you can’t get both at the same time.

What about Objective-C? It has static typing (with regular pointers)
and
kind of dynamic typing (“id” type). Maybe Ruby should have similar
capability? Or maybe I just told something really stupid?

I alway have to look up definitions…

Unfortunately I’m not familiar with Objective C so I can’t judge on
that.

I cannot say I know Objective C well too, but I get some basic concepts.

From what I’ve seen so far I’d assume it’s similar to Java which is
regarded
as statically typed although you have access to type information at
runtime
(as seems to be the case with Objective C). But the crucial part is
that
you declare types (of variables, of method arguments) in code and
these
types are checked by the compiler.

But the feature I described in my previous post has no equivalent in
Java - I’ll try to explain it (I may be very wrong, so anyone knowing
Obj-C better please correct me):

In Obj-C, when you create a variable to hold a pointer to an object of
class Object, you have 2 choices:

Object *obj;
id obj;

the second pointer is “typeless”, because it can point to an object of
any class. I wonder if similar mechanism could be useful in Ruby.

Ruby does not do this (as does Lisp, although it seems there are some
optimization type hints). So without these declarations it’s
difficult to
do type verification at compile time without code execution. To
introduce
this wuold be a major change in the language and break lots of code.
If you
would allow for typeless and typed method arguments at the same time,
you
would increase interpreter complexity by orders of magnitude and code
would
be a real mess. I don’t think, it’s a good idea.

I’ll try to explain my idea in more detail. I suggest that one could put
optional type information when declaring the variable, eg:

def some_method ( String str, second_param )

do |Array ar, smth, Fixnum int|

etc.

So basically, current typeless declaration would become something
similar to Obj-C’s id, and new typed one would be similar to Obj-C’s
Object*.

Note I don’t mean to change (dynamic) method dispatching here - I just
wish Ruby had some mechanism for type checking on variable assignment,
so I don’t get enigmatic error messages deep inside a library I use (but
I didn’t write). Of course such mechanism would not prevent some runtime
errors (given you can remove method from an object), but it would surely
be very useful (at least for me).

In other words, this feature would be equivalent of ‘strongtyping’
library, just with better syntax and compile-time checking (to avoid
runtime overhead).

But there’s a whole lot of problems waiting:

  • You need return type declarations (at least optional)
  • What do you do if you invoke a method with a required parameter type bu
    t your value resides in some typeless var?
  • You’ll likely and up casting values all the time => errors here can
    only be detected at runtime
  • Internal handling of references must be completele changed.
  • What do you gain by type info if any instance is free to override
    methods defined in the class at will?
    etc.

Although I can see the benefit for some users, I’m still not convinced
that this is a good idea, that it fits Ruby well and / or that this will
show up in Ruby in the near future. After all, it will make a lot of
Ruby’s simplicity go away. And I don’t think, Matz wants to go into that
direction.

Regards

robert
···

On Tue, 18 May 2004 08:48:04 +0200, Robert Klemme wrote:

Hi,

···

In message “Re: How to duck type? - the psychology of static typing in Ruby” on 04/05/18, Marek Janukowicz childNOSPAM@t17.ds.pwr.wroc.pl writes:

But the feature I described in my previous post has no equivalent in
Java - I’ll try to explain it (I may be very wrong, so anyone knowing
Obj-C better please correct me):

Tell me briefly what feature is not present in Java, and what you can
get by the feature, AFTER reading “duck typing” post [ruby-talk:100511]
VERY CAREFULLY.

I buy the flexibility from dynamic typing at the cost of compile-time
type check. I don’t think I am going to change my mind.

						matz.