Oppinions on RCR for dup on immutable classes

Yukihiro M. wrote:

|I’ll try to explain it differently, depict my issue. Say you go to a
|restaurant, take a look at the card and see “Spagetthi”. You order
|Spagetthi but the waiter just tells you “Oh, we don’t serve Spagetthi
|here.”. You’d naturally ask “Why put it on the card then if you don’t
|serve it at all?”

I imagine the waiter telling you “Oh, we don’t serve Spaghetti
today”.

          matz.

Um, no, with the classes mentioned in the RCR the answer would be
“never”, not just “today”. You’d have to buy the Restaurant and exchange
to cook to change the answer :slight_smile:

My regards

On 2/17/07, Dean W. [email protected] wrote:

As far as I understand, DuckTyping is not something based on method

                                                    matz.

For me, this does break the POLS, because it breaks the Liskov
Substitution Principle
you are opening a can of worms (or ducks if you prefer).

I would say that LSP does not apply here simply because in Ruby we do
not have that kind of contract.
In order to apply LSP we need to say at at a point hey here we have an
object of class Base.(let the gods forgive me that I use Java)
void aMethod(final Base b){

}
and we expect this to work whenever we call aMethod with an object
that is a Base.
Anyway the compiler would not really allow otherwise.

SubClass sc; // subclassing Base od course
aMethod( sc ); // this is expected to work (from the type POV).

Such things just do not exist in Ruby, I believe that Ruby has
explained something to me:

OO Languages are Class oriented languages
Dynamic Languages are Object oriented languages.
Replace Class with Type and you see what I mean.

This is all very much IMHO of course but I feel that the Ruby
community has made me evolve a lot away from “Class oriented”.

(loosely, "an object of a derived type can be

substituted for an object of a base type", for those of you who
haven’t heard of it…). LSP is essentially the underpinnings of
Bertrand Meyer’s “Design by Contract”.

If I’m iterating through a collection of objects and all of them
respond_to? a method, yet an exception is thrown in some cases, that’s
surprising :wink:

Do not let your code surprise you. If it does than it is not the
language’s fault.
But I have seen the smiley :wink:

The deep-copy scenario is a good one. In this case, it
would be nice to have a succinct way of copying the object graph
without having to worry about some dup methods “not working”.

Meaning not worrying about the semantics of your program ???
But you still have a good use case below, not good enough for a RCR but
good. → see my last point too please.

“contract” can’t be satisfied transparently by all derivatives. Maybe
that’s just the price we have to pay for being rich :wink:

Instead of advocating for a RCR especially in the present scenario which
is:
“Well that might be bad sometimes and goos sometimes, not really worth a
CR”
you might just create your own little toolbox.
class Integer … def dup etc.

Advocating is a good thing but it is not the only one.
After some months of using your toolbox you might still want the CR or
maybe throw it away, who knows?

Cheers
Robert

P.S.
I am against the CR but the discussion is a great one! Thumbs up!
R.

On Sun, 18 Feb 2007, Stefan R. wrote:

Care to explain why you chose defining a method with the sole purpose of
raising an exception over removing the method instead?

yes - for illustration :wink:

a simpler example

harp:~ > cat a.rb
require ‘singleton’

a = Object.new.instance_eval{ @x = 42 and self }
p a.dup

a.instance_eval{ class << self; include Singleton; end }
p a.dup

harp:~ > ruby a.rb
#<Object:0xb75cbb44 @x=42>
/home/ahoward//lib/ruby/1.8/singleton.rb:71:in `dup’: can’t dup
instance of singleton Object (TypeError)
from a.rb:7

this is a side effect of strong dynamic type systems: the
interpreter/compiler
cannot know until runtime if a methods signature makes sense becaues
there are
an infinite variety of ways the semantics of a msg sent to an object
might
change betweent two transmissions to the same object. if you don’t like
this
there are two choices:

  • use language with a strong static type system. this rules out
    python,
    java, c++, c, perl, lisp, and smalltalk

  • dispair

regards.

-a

On Sun, 18 Feb 2007, Stefan R. wrote:

My issue is that I can’t test that. I can only try and catch the exception.
With dup that’s not too terrible as it doesn’t have side-effects. Still in
my oppinion having to run code to see what happens is not a clean behaviour.

you should check out haskell - it’s one of only a few languages that can
provide this feature.

-a

On Sun, 18 Feb 2007, Stefan R. wrote:

I’ll try to explain it differently, depict my issue. Say you go to a
restaurant, take a look at the card and see “Spagetthi”. You order Spagetthi
but the waiter just tells you “Oh, we don’t serve Spagetthi here.”. You’d
naturally ask “Why put it on the card then if you don’t serve it at all?”

because we serve it sometimes. in addition, most of our employees know
how to
make it at any time. we might not have it today though. our we might,
but
we’re out of meatballs.

-a

Hi,

In message “Re: Oppinions on RCR for dup on immutable classes”
on Sun, 18 Feb 2007 01:37:19 +0900, Stefan R.
[email protected] writes:

|Um, no, with the classes mentioned in the RCR the answer would be
|“never”, not just “today”. You’d have to buy the Restaurant and exchange
|to cook to change the answer :slight_smile:

If we see a class as a restaurant, your illustration makes sense. But
from my point of view, we don’t know the name of the restaurant, nor
its menu. We just sit and cry for “Spaghetti!”, and sometimes the
waiter says “I’m sorry”.

          matz.

On Sun, 18 Feb 2007, Stefan R. wrote:

          matz.

Um, no, with the classes mentioned in the RCR the answer would be
“never”, not just “today”. You’d have to buy the Restaurant and exchange
to cook to change the answer :slight_smile:

not really, you just have to learn how to cook! :wink:

harp:~ > cat a.rb
module DupSelf
def dup() self end
end

nil.extend DupSelf

p nil.dup

harp:~ > ruby a.rb
nil

regards.

-a

On 2/17/07, Yukihiro M. [email protected] wrote:

If we see a class as a restaurant, your illustration makes sense. But
from my point of view, we don’t know the name of the restaurant, nor
its menu. We just sit and cry for “Spaghetti!”, and sometimes the
waiter says “I’m sorry”.

But they never do seem to run out of chunky bacon.

unknown wrote:

On Sun, 18 Feb 2007, Stefan R. wrote:

Care to explain why you chose defining a method with the sole purpose of
raising an exception over removing the method instead?

yes - for illustration :wink:

And in a real situation, why would you chose to do so? What would be the
reasoning to justify that?

this is a side effect of strong dynamic type systems

I am well aware of that. I used ruby for over a year :wink:
But you in this situations you have two options, define a method whichs
only code is “raise Exception” or not define the method at all.
Or in your example the choice is between redefining the method with one
whichs only code is “raise Exception” or undefine the existing one.
In both situations: why would you chose one over the other?
I’m sorry if I’m obnoxious with that :slight_smile:

My regards

Yukihiro M. wrote:

Hi,

In message “Re: Oppinions on RCR for dup on immutable classes”
on Sun, 18 Feb 2007 01:37:19 +0900, Stefan R.
[email protected] writes:

|Um, no, with the classes mentioned in the RCR the answer would be
|“never”, not just “today”. You’d have to buy the Restaurant and exchange
|to cook to change the answer :slight_smile:

If we see a class as a restaurant, your illustration makes sense. But
from my point of view, we don’t know the name of the restaurant, nor
its menu. We just sit and cry for “Spaghetti!”, and sometimes the
waiter says “I’m sorry”.

          matz.

The example translates to:
Restaurant := Class
Menucard := #methods
Say “we don’t serve that” := raised Exception

If it changes from time to time I agree with you. But if it is “never”,
the restaurant shouldn’t put the menu on the card in the first time - in
my oppinion :slight_smile:

My regards

Hi –

On Sun, 18 Feb 2007, Stefan R. wrote:

Say “we don’t serve that” := raised Exception
But methods are not constrained by class. It’s not the class’s
responsibility to oversee the object’s methods. I’m not sure where
the object fits into your model.

David

On 2/17/07, Gregory B. [email protected] wrote:

=> true

2.dup
NoMethodError: undefined method `dup’ for 2:Fixnum

Oh no, you don’t wanna do that: What if you’re a library and a user
assumes :dup is defined? What if you use a library that assumes it and
don’t know about it?

On 2/17/07, SonOfLilit [email protected] wrote:

Oh no, you don’t wanna do that: What if you’re a library and a user
assumes :dup is defined? What if you use a library that assumes it and
don’t know about it?

Um. then no one uses your library?

I’ve already made it clear I don’t think it’s a good idea in the
general sense, I’m just saying that if the behaviour change is
necessary or important to you, it’s easy to add.

Whether or not it’s good practice is an entirely seperate question.
I would be tempted to bludgeon library writers who find it convenient
to undef core methods, to be honest.

For client code that doesn’t have to play nice with others? Have at
it! (You are writing tests that make sure your code is working
right, aren’t you? :slight_smile: )

On Sun, 18 Feb 2007, Stefan R. wrote:

unknown wrote:

On Sun, 18 Feb 2007, Stefan R. wrote:

Care to explain why you chose defining a method with the sole purpose of
raising an exception over removing the method instead?

yes - for illustration :wink:

And in a real situation, why would you chose to do so? What would be the
reasoning to justify that?

the one that springs to mind is

module Mixin
def average
total.to_f / n.to_f
end
def total
raise NotImplementedError
end
def n
raise NotImplementedError
end
end

this give a much nicer error than NameError or something about nil not
responding to ‘to_f’.

another is

module DRbUndumped
def _dump(dummy) # :nodoc:
raise TypeError, ‘can’t dump’
end
end

this is more useful than it looks. what it means is that any object in
a
hierarchy will cause a particular exception to get thrown, indicating
that a
drb proxy should be used. this is a good approach because you can mark
objects
which are normally able to be marshaled as not being so in a way that’s
viral
to other objects holding references to this object.

this is a side effect of strong dynamic type systems

I am well aware of that. I used ruby for over a year :wink:

sorry for being pendantic then.

But you in this situations you have two options, define a method whichs
only code is “raise Exception” or not define the method at all.
Or in your example the choice is between redefining the method with one
whichs only code is “raise Exception” or undefine the existing one.
In both situations: why would you chose one over the other?
I’m sorry if I’m obnoxious with that :slight_smile:

that’s ok.

cheers.

-a

On 2/17/07, Stefan R. [email protected] wrote:

 def n

end
end

a) uses Rational if possible ;-p (ok, besides the point)
b) no superfluous code
c) no additional exception

I’m sorry, I still fail to see the point in defining a method that says
the method can’t be executed (put a menu that isn’t actually served on
the menucard - put it on the menucard when it is served)

the difference is in the rescue.

rescue NoMethodError

is not the same thing as

rescue NotImplementedError

Gregory B. wrote:

the difference is in the rescue.

rescue NoMethodError

is not the same thing as

rescue NotImplementedError

That’s getting off-topic. The error dup gives is “not possible”, not
“not implemented”. Different story.
If you check previous messages you might figure that I can understand
the use in abstract classes (or mixins here) even though I’d do it
differently.

My regards.

OO Languages are Class oriented languages
Dynamic Languages are Object oriented languages.
Replace Class with Type and you see what I mean.

This is all very much IMHO of course but I feel that the Ruby
community has made me evolve a lot away from “Class oriented”.

Interesting points, especially about the implications of
“class-centric” vs. “object-centric” programming.

It’s true that I rarely ever run into LSP issues, even in Java code. I
think it reflects, in part, the general movement OOD towards
de-emphasizing inheritance in favor of composition through
abstractions, etc. I would rather have the richness of Object and
Kernel, even with some LSP issues.

As someone else commented, perhaps the real issue is that
5.respond_to?(:dup) returns true yet 5.dup raises, so you have no way
of knowing in advance that you shouldn’t call dup.

On Sun, 18 Feb 2007, Dean W. wrote:

As someone else commented, perhaps the real issue is that
5.respond_to?(:dup) returns true yet 5.dup raises, so you have no way of
knowing in advance that you shouldn’t call dup.

i simply do not understand this line of thinking - every call to every
object
always has that characteristic

f.respond_to? :read #=> true
f.gets # EOFError

q.respond_to? :pop #=> true
q.pop(true) #=> ThreadError if empty

to me this really seems like a dynamic vs static issue - i just don’t
see how
ruby can save you, regardless of the impl of dup, or any other method.
one
cannot avoid hanlding runtime exceptions in a dynamic language. one
cannot
know in advance whether it’s ok to call something - even if the object
responds to it.

regards.

-a

unknown wrote:

the one that springs to mind is

module Mixin
def average
total.to_f / n.to_f
end
def total
raise NotImplementedError
end
def n
raise NotImplementedError
end
end

this give a much nicer error than NameError or something about nil not
responding to ‘to_f’.

module Mixin
def average
total().quo(n())
end
end

a) uses Rational if possible ;-p (ok, besides the point)
b) no superfluous code
c) no additional exception

I’m sorry, I still fail to see the point in defining a method that says
the method can’t be executed (put a menu that isn’t actually served on
the menucard - put it on the menucard when it is served)

My regards

On Sun, 18 Feb 2007 [email protected] wrote:

responds to it.
… or even if it doesn’t: method_missing

-a