[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Gedankenexperiment on method duck type safety

Tim Connor

1/31/2008 7:22:00 PM

*braces for the flames to follow*

I had a strange idea this morning, namely, how would I merge the idea
of the contractual nature of static type safety, with the flexibility
of duck-typing. I know, it's a hot button, and I've read various
other threads that come close, but don't quite address it the same
way.

And I am not seriously proposing this as a "good idea" or anything. I
was just thinking "hmm, is there any way to get ducktype safety,
without manually throwing ParameterErrors in the header of the method
if something fails a responds_to". Yes, there are times you want more
complex handling if something doesn't quack, but sometimes you do want
to enforce that, and right now it is just a bunch of extra ifs and
unlesses.

And I know this doesn't fit with he already complex enough method
declarations in ruby. It's just faux ruby style, because that is my
favorite dynamic language. So, without further prevarication, here is
the aforementioned abomination, for either discussion sake, or
pointing and laughing, whichever floats your boat:

def foo(bar.is_? Array, !bar.is_empty?, baz.responds_to :webbed_feet)
12 Answers

Eivind Eklund

1/31/2008 9:48:00 PM

0

On Jan 31, 2008 8:25 PM, Tim Connor <timocratic@gmail.com> wrote:
> And I know this doesn't fit with he already complex enough method
> declarations in ruby. It's just faux ruby style, because that is my
> favorite dynamic language. So, without further prevarication, here is
> the aforementioned abomination, for either discussion sake, or
> pointing and laughing, whichever floats your boat:
>
> def foo(bar.is_? Array, !bar.is_empty?, baz.responds_to :webbed_feet)

See code implementing something similar at
http://people.freebsd.org/~eivind/r...

typesig Type::And(Array, Type::RespondFalse(:is_empty?)),
Type::RespondTo(:webbed_feet)
def foo(bar, baz)
...
end

You'd have to implement Type::RespondFalse - should be trivial.

Eivind.

Tim Connor

1/31/2008 10:24:00 PM

0

> See code implementing something similar athttp://people.freebsd.org/~eivind/r...

I like your warning in the readme: http://people.freebsd.org/~eivind/r...README
and I wouldn't be surprised to find that being the case. I was
considering though if a less verbose approach would be more rubyish
and less painful. None of the extra pre-declaration required in the
usual type system, but just how to make method declarations more
explicitly contractual (looking at the contractual aspect more than
the type system aspect). I suspect it is still a case of YAGNI, as I
haven't really needed it yet, too much, but there are just some odd,
harder than they should be bugs I've had to trace.

Yeah tests and BDD helps a lot, and maybe a convention of always
testing the nil and edge cases for each parameter. But when something
nested goes awry, in a situation you know exactly what the function
wants (even if it's just a responds_to), it might be nice to get a
more immediate failure. Maybe that would interfere with refactoring
and lead to a more Javaesque inflexibility, though. I dunno, to be
honest. Which is why I posted. ;)

Apparently in your experience it just led to additional pain with
little benefit?

Robert Klemme

1/31/2008 10:35:00 PM

0

On 31.01.2008 20:22, Tim Connor wrote:
> I had a strange idea this morning, namely, how would I merge the idea
> of the contractual nature of static type safety, with the flexibility
> of duck-typing. I know, it's a hot button, and I've read various
> other threads that come close, but don't quite address it the same
> way.
>
> And I am not seriously proposing this as a "good idea" or anything. I
> was just thinking "hmm, is there any way to get ducktype safety,
> without manually throwing ParameterErrors in the header of the method
> if something fails a responds_to".

I tend to believe that this approach is at least ill named - if not
worse and here's why: If you test with respond_to? you are no longer
duck typing. If all you test is respond_to? then you gain nothing over
normal interpreter execution, exceptions are just thrown a bit earlier -
but at the price of more complex code or method declarations and runtime
overhead. Also, it's not _static_ type safety.

> Yes, there are times you want more
> complex handling if something doesn't quack, but sometimes you do want
> to enforce that, and right now it is just a bunch of extra ifs and
> unlesses.

Well, the interpreter will enforce it if methods are called that do not
exist on those objects.

> And I know this doesn't fit with he already complex enough method
> declarations in ruby.

Um, where is declaring methods in Ruby complex? I haven't noticed so far.

> It's just faux ruby style, because that is my
> favorite dynamic language. So, without further prevarication, here is
> the aforementioned abomination, for either discussion sake, or
> pointing and laughing, whichever floats your boat:
>
> def foo(bar.is_? Array, !bar.is_empty?, baz.responds_to :webbed_feet)

You can certainly squeeze this into Ruby - Ruby is so flexible and a lot
of people have done all sorts of weird things with the language. I
would not bother a second to seriously consider this...

Kind regards

robert

Thomas Wieczorek

1/31/2008 11:12:00 PM

0

Tim Connor

2/1/2008 2:15:00 AM

0

On Jan 31, 3:11 pm, Thomas Wieczorek <wieczo...@googlemail.com> wrote:
> I like the post on chicken typing here:http://talklikeaduck.denhaven2.com/articles/2007/10/22/chic......

Cool, I get better the argument being made for blind ducktyping now
(the soft/hard descriptors are somewhat misleading and not very, well
descriptive, imo), than just after reading the posts in this list.

Daniel DeLorme

2/1/2008 2:44:00 PM

0

Tim Connor wrote:
> *braces for the flames to follow*
>
> I had a strange idea this morning, namely, how would I merge the idea
> of the contractual nature of static type safety, with the flexibility
> of duck-typing. I know, it's a hot button, and I've read various
> other threads that come close, but don't quite address it the same
> way.
>
> def foo(bar.is_? Array, !bar.is_empty?, baz.responds_to :webbed_feet)

A lot of other people have gone down this road, but patching "static"
type checking into a dynamic language is IMHO futile. However I think
something interesting could be done with a static/compiled dialect of
ruby where method signatures are inferred from the method body. e.g.:

#this method requires an argument that responds to to_str
def foo(a)
a.to_str
end
foo("str") #compiles ok
foo(42) #compile error

you could also do method overloading:

def foo(a)
a.to_str
end
def foo(a)
a.to_ary
end

"static duck typing"
It's fun to think about, but soooo far beyond my skills ;_;

Daniel

Robert Klemme

2/1/2008 4:10:00 PM

0

2008/2/1, Daniel DeLorme <dan-ml@dan42.com>:
> A lot of other people have gone down this road, but patching "static"
> type checking into a dynamic language is IMHO futile.

Right.

> However I think
> something interesting could be done with a static/compiled dialect of
> ruby where method signatures are inferred from the method body. e.g.:

And how do you ensure only code compiles that satisfies this static
constraint? How do you make sure that only objects are passed that
satisfy this constraint? Basically this can only be done if you
statically explore all (and I mean *all*) possible execution paths of
a program. I believe this is impossible, especially in light of
compiled C extensions.

> It's fun to think about, but soooo far beyond my skills ;_;

Probably beyond *anybody's* skills in the case of Ruby. :-)

Kind regards

robert

--
use.inject do |as, often| as.you_can - without end

Thomas Wieczorek

2/1/2008 6:51:00 PM

0

Though I think that is_a? should be used sparsely. I like the idea of
gradual typing: Develop your program first without type definitions
and then when you think some regions need speed up, add the used types
of the objects.

Tim Connor

2/1/2008 8:52:00 PM

0

On Feb 1, 6:43 am, Daniel DeLorme <dan...@dan42.com> wrote:
>
> "static duck typing"
> It's fun to think about

Yeah, that was my main point all along; to see what I'd learn about
good practices, from the responses, if nothing else. The point that
the interpreter does throw an error eventually, so why worry about
making it earlier, for instance, is not entirely invalid.

I still think you can get weird bugs (hard to find or account for ones
that only surface on the missed corner case every so often) based on
violation of contract, if you don't remember to test in your method
preface/header each and every time. I mean, really who hasn't been
bitten by a bug that took some digging that had to do with a parameter
not meeting some of their assumptions?

On the other, I do love the grace, ease, and verbosity of ruby's loose
typing. If I ever have to go back to a statically typed language,
particularly one as verbose about it has Java or C#, it's going to
hurt.

Rick DeNatale

2/2/2008 12:33:00 AM

0

On Feb 1, 2008 3:55 PM, Tim Connor <timocratic@gmail.com> wrote:
> I mean, really who hasn't been
> bitten by a bug that took some digging that had to do with a parameter
> not meeting some of their assumptions?

Yes, and that happens with statically typed languages, actually those
bugs tend to be harder to diagnose with static languages.

Most of the really awful things which can happen in statically typed
languages which can be caught by static type checking are caused by
the fact that the compiled code relies on static types. For example
in C++, it would be really bad if a member of an object was 'accessed'
when the object was of the wrong type, since accessing is done by
early (compile-time) bound offsets. Dynamically typed languages
trade off a little bit of run-time performance for safety or at least
serviceability by deferring such bindings to run-time and checking
them.

Other very common 'type' mistakes such as array bounds errors aren't
caught by most statically typed language compilers, yes some advanced
type systems attack this problem but it's still considered an advanced
type-theory issue in practice. So most statically typed languages
defer bounds checking to run-time if they do it at all.

Back in the days when the arguments raged about C+ vs. Smalltalk,
Bjarne Stroustrup was wont to say that he didn't want to fly in a
plane where the autopilot could throw a does_not_understand exception,
my feeling that that would be better than the autopilot branching to a
virtual function through a corrupted or type-punned pointer.


--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...