Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > The duck's backside

Reply
Thread Tools

The duck's backside

 
 
Robert Dober
Guest
Posts: n/a
 
      05-29-2008
On Thu, May 29, 2008 at 12:37 PM, David A. Black <> wrote:

>
> The idea of duck typing, as I understand it, is to embrace this
> inalterable fact about Ruby objects, rather than try to wish it away,
> with ancestry checks and the like. This makes sense to me; it stands
> to reason that a language with objects whose types can change during
> runtime would be well-served by a programming style that deals as
> directly and economically as possible with precisely that condition.


I have to admit that I was quite disappointed that my implementation
of traits got so few feedback. That is not the personal disappointment
that comes simply for the reason that one wants to share a project and
cannot as it does not interest others, that is a risk to take of
course .
It surprised me though that Rubiests that I learnt to like and
respect, like e.g. you Dave, still use the terms "types" and "classes"
as
if they were not in contradiction to what they are saying about duck
typing afterwards.

With traits we are exactly talking ducktyping, we combine behavior,
which we try organize intelligently and forget about inheritance and
is_a? modeling. It really gives us the chance to implement
applications without abusing of inheritance. The beauty of Ruby is of
course that single inheritance and Mixins are still available for
projects where this is appropriate, and there are many.

The bold statement I will make now is the following: Whenever a
projects seems best suited to use ducktyping as its dominant design
scheme, traits (as e.g. in Squeak) or prototypes ( as e.g. in
Javascript) somehow seem a more natural approach than classes and
mixins.

Now using mixins extensively (pun intended) is a good thing especially
if we refrain from abusing is_a?, Module#=== ed altri.
It can lead to beautiful designs(1), but so can using traits and prototypes

(1) beware of the double inclusion trap though

Cheers
Robert

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

 
Reply With Quote
 
 
 
 
David A. Black
Guest
Posts: n/a
 
      05-29-2008
Hi --

On Thu, 29 May 2008, Robert Dober wrote:

> On Thu, May 29, 2008 at 12:37 PM, David A. Black <> wrote:
>
>>
>> The idea of duck typing, as I understand it, is to embrace this
>> inalterable fact about Ruby objects, rather than try to wish it away,
>> with ancestry checks and the like. This makes sense to me; it stands
>> to reason that a language with objects whose types can change during
>> runtime would be well-served by a programming style that deals as
>> directly and economically as possible with precisely that condition.

>
> I have to admit that I was quite disappointed that my implementation
> of traits got so few feedback. That is not the personal disappointment
> that comes simply for the reason that one wants to share a project and
> cannot as it does not interest others, that is a risk to take of
> course .
> It surprised me though that Rubiests that I learnt to like and
> respect, like e.g. you Dave, still use the terms "types" and "classes"


s/Dave/David/

> as
> if they were not in contradiction to what they are saying about duck
> typing afterwards.


Sorry, I'm not sure which contradiction you're talking about. Can you
clarify?


David

--
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 23-26 London (Skills Matter)
See http://www.rubypal.com for details and updates!

 
Reply With Quote
 
 
 
 
Robert Dober
Guest
Posts: n/a
 
      05-29-2008
On Thu, May 29, 2008 at 1:35 PM, David A. Black <> wrote:

>
> s/Dave/David/

s /^/So sorry, why does this always happen to me?/
>
>> as
>> if they were not in contradiction to what they are saying about duck
>> typing afterwards.

>
> Sorry, I'm not sure which contradiction you're talking about. Can you
> clarify?


Contradiction is maybe a too strong a word, let me put it like this,
IIUC, you and others made some interesting points about static
modeling and ducktyping as one way of a more dynamic approach fitting
Ruby's dynamic nature quite well. As many people on this list I
completely adhere to this statement.

I however have always thought that it was kind of exploring an
interesting road without trying some new paths. E.g. using prototypes
instead of inheritance and mixins or traits. Prototypes have been
around for quite some while as a result of Ara's work, though I am
afraid it is broken now.
I have delivered a more primitive implementation (very slow 10*slower
than mixins) of prototypes and a quite acceptably performing traits
implementation (5*slower for 1.8, 2*slower for 1.9 although it could
be faster than inheritance and mixins in a far future, but this is not
really an issue here).
Now I do not really want to promote my packages here, I will not even
make the noise of putting uris here, those intersted can search for
Labrador and ruby-traits on Rubyforge. What I want is to encourage
people to go ahead, not accepting things as they are, forgetting of
inheritance and mixins sometimes and try out some different
approaches, not necessarily mine.

And all that simply because I feel that establishing is_a?
relationships does not really make much sense if we do not use them.
The polymorphic approach is not at all limited to the static
inheritance scheme, it is even much more ducktypier than that. And
that is why I believe that using class and inheritance and mixins is
often convenient and very often not a problem at all, but it is maybe
more a tool than a concept in Ruby.

Pheww I hope I got some messages across if not sorry for the waste of bandwith.

Cheers
Robert
>
>
> David
>
> --
> 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 23-26 London (Skills Matter)
> See http://www.rubypal.com for details and updates!
>
>




--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

 
Reply With Quote
 
Mark Wilden
Guest
Posts: n/a
 
      05-30-2008
[Note: parts of this message were removed to make it a legal post.]

On May 29, 2008, at 2:14 AM, David Masover wrote:
>>


>> I can say
>> quite categorically, that in OOP, classes are ways to generalize. You
>> generalize based on characteristics and behaviors. A class is not
>> simply a random collection of methods. It would be rather useless if
>> class was unrelated to category.

>
> I'm going to have to respectfully disagree here.


I'm not sure what you're disagreeing with, here. That classes are
categories? If so, I could refer you to any number of the sources I
learned OOP from - except that I've given them all away by now.

If classes are not categories, what are they?

> Unless you are going to have branching based on type -- that is,
> simple method
> overloading (as in C++ and friends) -- I don't see as much point to
> a rigid
> type system.


I've done a lot of C++, and I remember when RTTI (runtime type
information) was introduced. I was pretty strongly against its use,
believing that polymorphism through virtual functions was the way to
"branch" on type. I would have strongly avoided code like v === Numeric.

As I would avoid it today, in Ruby. We're actually talking about
something that I think should be rare, which is branching on type.
We're only doing it to validate parameters. In good Ruby, we would not
do this, relying on the runtime to tell us when we're using the wrong
type. To me, duck typing doesn't mean "ask me if I quack" as much as
"quack, you!". So I think this whole discussion is about an edge case.

> It boils down to: Why should I care whether I'm being passed a
> number or
> something which merely behaves like a number? Why should I care if
> I'm being
> passed a string or an array of characters?


Actually, I agree, in general, and this discussion has clarified the
concept for me.
>
> Now, for the simple case of a Numeric, we're probably over-analyzing
> it.


Yes, I don't think I would have made the same case for a less basic
class.

However, I still think using responds_to? to identify an object's type
is risky. As I said, it relies upon a much larger namespace than class
constants, hence much more chance for accidental positives (e.g.,
#draw meaning different things to different objects).

>> But I'm finding these remarks about "attititude" kind of amusing.
>> It's
>> like Ruby isn't a tool, it's a "mindset." We don't forgo something
>> like Numeric === v because it's _wrong_ (the OP in fact said it was
>> slightly more readable), but because Ruby has duck-typing,

>
> Well, there is some truth to that -- as an example, Ruby completely
> lacks
> anything resembling the C for loop. If that's what you're expecting,
> you have
> to build it out of a while loop:
>
> i=0
> while i < data.length
> do_something_with data[i]
> i += 1
> end
>
> There's nothing wrong with that. But I hope most of us forgo it in
> favor of:
>
> data.each { |datum|
> do_something_with datum
> }
>
> Which ends up being more readable, among other things.


Exactly. It has absolutely nothing to do with Ruby's "mindset," or
"the way we do things in Ruby." We choose the latter because it's
better, not because it's the Ruby way. It's the other way around: it's
the Ruby way because it's better; not that it's better because it's
the Ruby way. The former attitude is pragmatic, the latter is religious.

> But if you do that, I don't understand why you're using Ruby. Again,
> nothing
> wrong with it -- do whatever makes you happy, and maybe you're right
> and I'm
> wrong. But I doubt I'll ever understand it.


There _is_ something wrong with it. It's harder to read and more prone
to error.

> Can you outline a few real-world examples, where it's OK to get a
> descendant
> of Numeric, but not something which merely implements to_i or to_f?


The obvious case is an object that implements to_i in a noncongruent
way. For example, let's say the number passed in is to be used as a
count. An IP address may respond to to_i, but it can't possibly be
correct in this context.

>> True. And often the most straightforward and fundamental way to do
>> that is to call its #class method.

>
> Not really.
>
> Firstly, #class doesn't provide any way to be in multiple
> categories. Ruby
> doesn't support multiple inheritance.


We're not talking about multiple categories - just one. In all my
years of using MI in C++, I've very rarely, if ever, seen a class that
didn't have a "dominant" base class. Most of the time MI is used for
mixing in. You might have a class, for example, that descends both
from Numeric and Observable, but obviously, its main category is
Numeric. In the case under discussion, I don't think multiple
categories are relevant.

At any rate, even if you don't think we should be using #class, you
can sure bet the language disagrees! We wouldn't get very far without
it.

I was emailcommunicado for a day or so, so I'm trying to catch up and
I'm running out of steam, here. ...

///ark
 
Reply With Quote
 
Mark Wilden
Guest
Posts: n/a
 
      05-30-2008
On May 29, 2008, at 3:37 AM, David A. Black wrote:

> Duck typing, as a way of thinking, meshes nicely with Ruby, as a tool,
> because of how Ruby objects are engineered: the *only* thing that you
> can measure with certainty is what an object does when you send it a
> message.


No, you cannot possibly measure with certainty what an object does
when you send it a message. The only thing you can measure is whether
it will throw a runtime error because it doesn't implement a method
for the message.

> You can ask it what its class is, what its ancestors are,
> what methods it responds to, and so forth... but in the end, you hit
> the singularity: the sending of the message.


However, an object's class and ancestors _determine_ what messages an
object responds to. That's what they're there for - to hold message
maps.

> it stands
> to reason that a language with objects whose types can change during
> runtime would be well-served by a programming style that deals as
> directly and economically as possible with precisely that condition.


Hmmm. Is it that objects change their type, or is it that variables do?

///ark

 
Reply With Quote
 
Mark Wilden
Guest
Posts: n/a
 
      05-30-2008
On May 29, 2008, at 1:49 AM, F. Senault wrote:

> Le 29 mai =E0 06:45, Eleanor McHugh a =E9crit :
>>
>> Numeric may well mean "numeric" in some particular sense, but that is
>> only a subset of all objects which may have a valid numeric
>> representation. As I said, you're applying a static typing mindset to
>> a place where it's not necessary and whilst Ruby will let you do =20
>> that,
>> in the long term you'll find yourself doing much more work with very
>> little (if any) gain in software robustness.


Man, I'm really not giving these replies the attention they deserve, =20
but I did want to mention one thing:

This has nothing to do with "static typing." "Static typing" refers to =20=

type checking being performed at compile-time instead of runtime. It =20
has nothing to do with interrogating an object's class during the =20
execution of a program. If you think about it, the class of an object =20=

is _continually_ being interrogated at runtime, in order to dispatch a =20=

given message to the right method.

///ark=

 
Reply With Quote
 
Mark Wilden
Guest
Posts: n/a
 
      05-30-2008

On May 29, 2008, at 1:18 AM, Bill Kelly wrote:
>
> From: "Mark Wilden" <>
>>
>> So if I can solve a programming problem simply by asking what
>> builtin class an object is, as opposed to seeing if it responds to
>> a certain method name, knowing nothing about what that method
>> actually does, I'll go with the former.

>
> There are more ducks in heaven and earth, Horatio, than are
> dreamt of in your philosophy.
>
>>> require 'delegate'

> => true
>>> x = SimpleDelegator.new(123)

> => 123
>>> x.class

> => SimpleDelegator
>>> x.kind_of? Numeric

> => false
>>> x.is_a? Numeric

> => false
>>> x.respond_to? :to_int

> => true
>>> x.to_int

> => 123


Good point.

///ark

 
Reply With Quote
 
Mark Wilden
Guest
Posts: n/a
 
      05-30-2008
[Note: parts of this message were removed to make it a legal post.]


On May 29, 2008, at 3:47 AM, Michael T. Richter wrote:

> On Thu, 2008-05-29 at 07:23 +0900, Mark Wilden wrote:
>>
>> One of the purposes of classes in OOP is to categorize things.

>
> One of the weaknesses of classic Booch, et al OOP is that one of the
> purposes of classes in OOP is to categorize things.
>
> Classes in classic OOP languages conflate a variety of concepts and
> cram them into one structure which does none of them particularly
> well:
> Classes are the unit of state.
> Classes are the unit of access control.
> Classes are the unit of functional dispatch.

These are simply the attributes of a type: a set of possible values
and a set of possible operations.

///ark


 
Reply With Quote
 
Tobias Weber
Guest
Posts: n/a
 
      05-30-2008
In article <89939D76-01F7-4223-B5CF->,
Mark Wilden <> wrote:

> > it stands
> > to reason that a language with objects whose types can change during
> > runtime would be well-served by a programming style that deals as
> > directly and economically as possible with precisely that condition.

>
> Hmmm. Is it that objects change their type, or is it that variables do?


As far as I'm concerned objects do not have a type, only variables do.
It determines what objects they can reference based on a trait like
class, ancestor, interface. In Java.

So I'd say that Ruby doesn't even have types. You can never know in
advance what methods the object in a certain variable might respond to.

And since message-maps are per-object, typed variables wouldn't even
change that. Just like neither kind_of? nor .class === can help you.

responds_to? does help, but can return false negatives if the target
overrides missing_method.

Consequently the most economic style for a Ruby method would be to just
take whatever argument comes in and fire some messages. Deal with any
excpetions. And at critical points maybe check the resulting value for
tangible properties like > 0 or empty?.

--
Tobias Weber
 
Reply With Quote
 
Robert Dober
Guest
Posts: n/a
 
      05-30-2008
On Fri, May 30, 2008 at 3:12 PM, Mark Wilden <> wrote:

> If classes are not categories, what are they?


A convenient tool for specifying behavior and using inheritance and
mixins for code reuse.
At least that is what Ruby classes give us. Free to you to apply
paradigms that can be implemented with this tool. To claim that Ruby
classes *are* that kind of paradigms does not meet my approval. Maybe
classes are very easily to be used as categories but I do not know
that.
>
> I've done a lot of C++, and I remember when RTTI (runtime type information)
> was introduced. I was pretty strongly against its use, believing that
> polymorphism through virtual functions was the way to "branch" on type. I
> would have strongly avoided code like v === Numeric.

For a very good reason, because it is Numeric === v.
But I feel a need to to justify my original reply to OP, he just
really needed that kind of check to make something work quickly, so I
showed him how to do it.
I however completely agree with you that code like that rings an alarm bell.
>
> As I would avoid it today, in Ruby. We're actually talking about something
> that I think should be rare, which is branching on type.

I boldly (my turn now state that there is no type in Ruby, but I
know what you mean and still agree!
>We're only doing it
> to validate parameters. In good Ruby, we would not do this, relying on the
> runtime to tell us when we're using the wrong type. To me, duck typing
> doesn't mean "ask me if I quack" as much as "quack, you!".

I would not like to ban early failure checks like that totally. Again
it just rings an alarmbell, but in some contexts TTD is difficult and
then extremely defensive programming might be in order,.
> So I think this
> whole discussion is about an edge case.

Right indeed, this was forgotten OP even stated so, good point.
>> Now, for the simple case of a Numeric, we're probably over-analyzing it.

>
> Yes, I don't think I would have made the same case for a less basic class.


For me there is a substantial difference though, and my bad that I did
not mention it in my
original post. Checking things like Integer ===, or String === are
surely less errorprone than
MyOwnClass ===, as I strongly feel that the randomly chosen Ruby
programmer will mess around with them less, especially when it comes
to override or revoke standard behavior.
>
> However, I still think using responds_to? to identify an object's type is
> risky.

It is even plain wrong, it specifically ask if behavior carrying a
given name is implemented or not, well you put that quite nicely into
the next sentence anyway
> As I said, it relies upon a much larger namespace than class
> constants, hence much more chance for accidental positives (e.g., #draw
> meaning different things to different objects).


>
>>> But I'm finding these remarks about "attititude" kind of amusing. It's
>>> like Ruby isn't a tool, it's a "mindset." We don't forgo something
>>> like Numeric === v because it's _wrong_ (the OP in fact said it was
>>> slightly more readable), but because Ruby has duck-typing,

It really feels wrong because indeed each tool creates its own
mindset, yet people are quite tolerant with it, but you just have to
remember all the time in Ruby (not as a mindset but as a simple
consequence of how Ruby works)

Class != Behavior

>> There's nothing wrong with that. But I hope most of us forgo it in favor
>> of:
>>
>> data.each { |datum|
>> do_something_with datum
>> }

Amen.
>>
>> Which ends up being more readable, among other things.

>
> Exactly. It has absolutely nothing to do with Ruby's "mindset," or "the way
> we do things in Ruby." We choose the latter because it's better, not because
> it's the Ruby way.
>It's the other way around: it's the Ruby way because it's
> better; not that it's better because it's the Ruby way. The former attitude
> is pragmatic, the latter is religious.

Strangely enough I see it the other way round:
"It is better" ( a very dangerous statement indeed) seems dogmatic to me.
using the mindset implied by semantics OTOH feels very pragmatic.
>> Firstly, #class doesn't provide any way to be in multiple categories. Ruby
>> doesn't support multiple inheritance.

You just have come to the end of your own argument I am afraid. Not
being an expert
I might be wrong of course, do you mean that mixins are not powerfull
enough to satisfy that model?
Robert

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57