The duck's backside

A

Avdi Grimm

Well, the desired goal is in fact to recognize objects that are numeric. One
of the purposes of classes in OOP is to categorize things.

Not really, no. That reflects an attitude that has more to do with
C++ or Java than with OOP. Not everything which behaves as a number
will inherit from Numeric, so that makes it useless and potentially
misleading as a categorization tool.

If you want you know whether an object is in some category in an OO
way, you come up with a way to ask it. E.g. if you want to know if an
object is iterable, you ask it if it responds to #each. Or you simply
treat it as if it is in that category, and see what happens. If you
want to *assert* that object to must be in a category, you tell it to
convert itself (and it will tell you if it can't).

With that said, I'm not really on the fanatical duck-typing end of
things either. I believe there is value in doing proactive contract
checking at what I will call for lack of a better term "package
boundaries". Duck-typing errors are not always obvious or easy to
track down. I like to have firewalls that I can be fairly confident
will catch faulty assumptions in a straightforward and obvious way,
without having to work back along the chain from a secondary or even
tertiary side-effect of an object failing to quack. For this reason
I've been known to put pre- and post-condition assertions in layers of
code that interact with third-party code.

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com
 
E

Eleanor McHugh

The only point of using Ruby (or any other tool in the universe) is
to get a job done. :) I would never use a Ruby feature just because
Ruby makes it possible.

Numeric === v is not a static typing convention (see http://en.wikipedia.org/wiki/Type_system)
. It's just OOP. It says in computer-understandable terms exactly
what you expressed in English: "v is numeric."

No, it states that v inherits from the base class Numeric, and that is
very much a static typing mindset, just projected onto an OO idiom.
However Ruby is very much a dynamic language in which an instance of
an object is not defined purely in terms of a chain of class
inheritance, or even of mix-ins because an instance can have new
methods directly attached to it. This being the case it makes much
more sense to see if an instance responds to a given message of
interest and then to act accordingly than to try and make assumptions
based upon incomplete inheritance information.
I don't even know what the ability to respond to :to_int means. Does
that mean the entity is numeric? Does a numeric string qualify? Does
a floating point number qualify? Could Array support this method?
Does every class that responds to to_int do semantically equivalent
things? (think Cowboy#draw and Artist#draw). The only way to tell is
to test it or look it up.

Yes. But as to_i, to_int, to_f, to_a, to_s and to_str are well known
messages you can have a high confidence that when these are present in
an instance they mean exactly what you expect them to mean. In
practice this extends to a much larger vocabulary.
This doesn't make it "marginally" less readable than Numeric === v,
IMO.

Different strokes, of course...

Exactly. If you don't like Duck Typing don't use it. It's perfectly
possible to design code in Ruby similarly to the way you would in Java
or C++ if that's what you're comfortable with. Just don't be surprised
if you find yourself writing a lot more code than is necessary.


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
 
E

Eleanor McHugh

:to_i is actually rather different, as it will convert a string
(even a non-numeric string like "2a"). That's an example of having
to know the implementation of the method to determine whether
testing responds_to? makes sense. For all I know, :to_i may in fact
be the desired method, but Elizabeth used :to_int, and I assume it
was for a reason.

I used to_int because it happened to be the synonym that popped into
my head at the time I was writing the code. It probably makes more
sense to use to_i though as that's often implemented outside the
Numeric class hierarchy for objects which can be represented by an
integer.
That's true, but it wasn't my point. The question is whether all
methods with the same name in all active classes should be
semantically equivalent. I think that's a rather larger assumption
than that Numeric means "numeric."

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 that,
in the long term you'll find yourself doing much more work with very
little (if any) gain in software robustness. In fact if you're writing
a library you'll introduce additional fragility to code interfacing
with it because Ruby programmers generally expect Duck Typing and
write accordingly.


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
 
M

Mark Wilden

Not really, no. That reflects an attitude that has more to do with
C++ or Java than with OOP.

I must respectfully disagree. I learned OOP (in 1989) before C++ was
even hardly available on PCs, much less Java. The OOP language I
learned was an amalgam of Smalltalk and Lisp. I cut my teeth on
Bertrand Meyer, Adele Goldbert, Brad Cox, and Grady Booch. 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.

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, and why use
Ruby if you can't duck type? I hope I'm not the only person to see how
totally back-asswords this kind of argument is.
Not everything which behaves as a number will inherit from Numeric,
so that makes it useless and potentially misleading as a
categorization tool.

And not everything that implements #to_int will be numeric, or can
even be converted to a number in a meaningful way for a context that
expects numbers. It's implementer's choice. However, the use case
might be that any object with that method is fine and dandy. In that
case, I totally agree that checking for response to it is reasonable,
if not 100% reliable. But if we're looking for Fixnums, Floats, and
other builtin classes, then checking again Numeric seems
straightforward.

The presence of a method called #each does not make an object
iterable. The only way that would be possible is if everyone who wrote
an #each method decided that was what it meant. What does show far
more accurately whether it's iterable is whether it includes
Enumerable. Including Enumerable shows that the #each method is for
iterating, rather than pricing, or something else.
If you want you know whether an object is in some category in an OO
way, you come up with a way to ask it.

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

I like duck-typing. It distinguishes great OOP languages like
Smalltalk and Ruby from wannabes like C++ and Java. But classes are
not simply random collections of methods. Their power is indeed to
categorize and generalize objects, which can be specialized with
inheritance (another old school concept, I suppose). 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. It's just the simplest thing that could possible work. But
wait--maybe that hoary criterion is out of fashion too?

///ark
 
T

Tobias Weber

Mark Wilden said:
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, and why use
Ruby if you can't duck type? I hope I'm not the only person to see how

My code worked before I started the thread. Like many posts around here
I asked how to make it more Ruby. The reason being that I believe the
language was designed by better programmers than myself, and that wholly
embracing their philosophy will bring me farther than just applying what
I learned in 'lesser' languages. That might change once I transcend all
implications of duck typing ;)
 
B

Bill Kelly

From: "Mark Wilden said:
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.
=> 123


Regards,

Bill
 
F

F. Senault

Le 29 mai à 06:45, Eleanor McHugh a écrit :
On 28 May 2008, at 23:23, Mark Wilden wrote:

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 that,
in the long term you'll find yourself doing much more work with very
little (if any) gain in software robustness. In fact if you're writing
a library you'll introduce additional fragility to code interfacing
with it because Ruby programmers generally expect Duck Typing and
write accordingly.

BTW, your code makes in fact two assumptions :

- The object has a valid numeric value (via .to_i(nt) in your case),
- But also that the object has a _string_ representation that happens to
be that numeric value (via the #{} interpolation).

Wouldn't it be better to write this :

@post "first=#{a}&" + (b.nil? ?
"second=ignored&third=#{v.to_int}" :
"second=#{v.to_int}&third=ignored")

Fred
 
D

David Masover

I must respectfully disagree. I learned OOP (in 1989) before C++ was
even hardly available on PCs, much less Java. The OOP language I
learned was an amalgam of Smalltalk and Lisp.

That's interesting.

It's my understanding that Ruby borrows its concept of "sending messages" from
Smalltalk, which lets us do things like #send and #method_missing.
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. Having done prototype-based
development in JavaScript, as I understand it, it's far easier to implement a
class-based system on top of a prototype system than the other way around.

In fact, I've seen it done, in various ways, with varying degrees of success
and usability.

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.

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?

Or even, why should I care if I'm being passed a real local object, or a proxy
to a remote object? Check this out:

http://ruby-doc.org/core/classes/DRb/DRbObject.html

Now, for the simple case of a Numeric, we're probably over-analyzing it.
There's not a huge amount of potential for replacing it with something
Numeric-like that does the same job, and we can easily see where relying on
to_i might (in VERY unlikely circumstances) give us something we don't want.
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 += 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.

It's not absolute. There are cases where you want traditional looping
constructs instead of Ruby iterators, and there are cases you want classes
instead of duck typing. But these are the exception, not the rule.

I won't stop you from using Ruby if you'd rather build for loops. Maybe you'll
get better at it:

data.length.times { |i|
do_something_with data
}

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.
However, the use case
might be that any object with that method is fine and dandy. In that
case, I totally agree that checking for response to it is reasonable,
if not 100% reliable. But if we're looking for Fixnums, Floats, and
other builtin classes, then checking again Numeric seems
straightforward.

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

Second, given no context, there's not really any way I could override class to
provide multiple membership. I'm either an Array or I'm a String. I can't be
both.

(Actually, I could probably pull something incredibly sneaky by returning an
object which pretends to be a class, and returns true when compared to other
classes on some list -- but I think I'd have to override some methods in
Class and/or Module to make it bulletproof.)

Now, we could meet halfway. All Numerics define #integer?, which responds True
for Integer and Bignum, and false for everything else. Object defines #nil?,
which is true for NilClass and false for everything else. And, worst case,
calling the object's own #kind_of? method gives me a place to override that
type check -- I don't believe that the Class === obj syntax allows that.
Their power is indeed to
categorize and generalize objects, which can be specialized with
inheritance (another old school concept, I suppose).

Inheritance can be approximated in Ruby with mixins. In JavaScript, it's
actually possible to write mixin functionality from the ground up -- create a
new class, and define it as a collection of methods from selected other
classes, plus a new collection you define right here.

I'm not sure I know how to implement ad-hoc prototypes and things like
#define_method from pure inheritance semantics. I am sure I can create
inheritance out of pure prototype semantics.
 
D

David A. Black

Hi --

I must respectfully disagree. I learned OOP (in 1989) before C++ was even
hardly available on PCs, much less Java. The OOP language I learned was an
amalgam of Smalltalk and Lisp. I cut my teeth on Bertrand Meyer, Adele
Goldbert, Brad Cox, and Grady Booch. 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.

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, and why use Ruby if you can't
duck type? I hope I'm not the only person to see how totally back-asswords
this kind of argument is.

Dave Thomas, who coined the term "duck typing", has described it as
"a way of thinking about programming in Ruby." So it is, in that
sense, a matter of attitude. The term has been beaten and battered
over the years to the point of unrecognizability, but it's pretty
simple in its original form.

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. 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. At that moment, whatever
is going to happen will happen.

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.


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!
 
R

Robert Dober

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
 
D

David A. Black

Hi --

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!
 
R

Robert Dober

s/Dave/David/ :)
s /^/So sorry, why does this always happen to me?/
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
 
M

Mark Wilden

[Note: parts of this message were removed to make it a legal post.]

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 += 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.
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
 
M

Mark Wilden

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
 
M

Mark Wilden

Le 29 mai =E0 06:45, Eleanor McHugh a =E9crit :

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=
 
M

Mark Wilden

[Note: parts of this message were removed to make it a legal post.]


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
 
T

Tobias Weber

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?[/QUOTE]

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?.
 
R

Robert Dober

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

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top