Oppinions on RCR for dup on immutable classes

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 Rusterholz wrote:

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

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

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

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

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

···

On Sun, 18 Feb 2007, Stefan Rusterholz 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?"

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

Hi --

···

On Sat, 17 Feb 2007, ara.t.howard@noaa.gov wrote:

On Sat, 17 Feb 2007 dblack@wobblini.net wrote:

You could conceivably have a case where an object can't be dup'd, but is
mutable, like a singleton class. If dup returns self, then you could end up
changing the object when you didn't want to. It's probably not an everyday
problem... but I still don't like the idea of having to remember that "dup"
means "dup or self".

you already do though?

harp:~ > cat a.rb
#
# crappy
#
h = { :point => 'we already have' }

h2 = h.dup

h2[:point] << ' that problem'

p h[:point]
#
# crappy
#
h = { :point => 'we already have' }

h2 = h.clone

h2[:point] << ' that problem'

p h[:point]
#
# sledge hammer
#
h = { :point => 'an imperfect solution' }

mcp = lambda{|obj| Marshal.load(Marshal.dump(obj))}

h2 = mcp[ h ]

h2[:point] << ' is to use marshal'

p h[:point]

harp:~ > ruby a.rb
"we already have that problem"
"an imperfect solution"

I don't consider returning a shallow copy the same as returning self.
It's not the same object as the receiver of the "dup" message.

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

IF the proposed implementation were to do what you suggested - rescue
every dup error by returning self - then I would agree that it's a bad
design feature to put into the language.

I personally believe that returning self for symbols, fixnums, true,
false, and nil is not bad or dangerous in any way. Can you provide a
single example (even if contrived) where this could produce an
unintended result? I can only come up with one myself, and it's too
contrived for me to consider it a danger.

···

On Feb 16, 3:28 pm, "Gregory Brown" <gregory.t.br...@gmail.com> wrote:

On 2/16/07, Robert Dober <robert.do...@gmail.com> wrote:

> On 2/16/07, Phrogz <g...@refinery.com> wrote:
> > b) You should never ever write "a.dup rescue a" because it will give
> > you strange problems if a might refer to a mutable object that doesn't
> > respond to #dup.
> Neve say never :wink: but when you write
> a.dup rescue a
> you should be aware of that potential danger

Right. My only point was that this solved what the OP asked for
without being hard.
It just seems like that solution is no better or worse than changing
the behaviour of dup, except for the fact that it puts the burden of
bad design into the programmer's hands, and not that of the
programming language :slight_smile:

Yukihiro Matsumoto 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

···

--
Posted via http://www.ruby-forum.com/\.

unknown 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

···

On Sun, 18 Feb 2007, Stefan Rusterholz wrote:

--
Posted via http://www.ruby-forum.com/\.

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

Oh, good point.

>> 1.respond_to?(:dup)
=> true

Then you need to rescue the exception.

If you *really* need this behaviour, you could just stick it in a file
somewhere and require it.

>> class Fixnum
>> undef :dup
>> end
=> nil
>> 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, Gregory Brown <gregory.t.brown@gmail.com> wrote:

On 2/17/07, Stefan Rusterholz <apeiros@gmx.net> wrote:

BTW, Matz, the only difference I suppose is that by having a
NoMethodError, we could make use of respond_to? as a check, but I
don't know if I think it's such a big deal that I'd be in support of a
RCR.

...

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.

···

...

you may not. neither do i. nevetheless it quite true that one must
understand __completey__ the rhs in

   d = obj.dup

in order to use d effectively.

-a

···

On Sat, 17 Feb 2007 dblack@wobblini.net wrote:

I don't consider returning a shallow copy the same as returning self.
It's not the same object as the receiver of the "dup" message.

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

>
> > > b) You should never ever write "a.dup rescue a" because it will give
> > > you strange problems if a might refer to a mutable object that doesn't
> > > respond to #dup.
> > Neve say never :wink: but when you write
> > a.dup rescue a
> > you should be aware of that potential danger
>
> Right. My only point was that this solved what the OP asked for
> without being hard.
> It just seems like that solution is no better or worse than changing
> the behaviour of dup, except for the fact that it puts the burden of
> bad design into the programmer's hands, and not that of the
> programming language :slight_smile:

IF the proposed implementation were to do what you suggested - rescue
every dup error by returning self - then I would agree that it's a bad
design feature to put into the language.

I personally believe that returning self for symbols, fixnums, true,
false, and nil is not bad or dangerous in any way. Can you provide a
single example (even if contrived) where this could produce an
unintended result? I can only come up with one myself, and it's too
contrived for me to consider it a danger.

the only things I can think of involve singleton methods

def nil.foo
  "hi there"
end

=> nil

nil.foo

=> "hi there"

b = nil.dup

TypeError: can't dup NilClass
        from (irb):13:in `dup'
        from (irb):13

def b.bar; "confusing?"; end

Imagine no error was thrown by that dup.

bar would be defined both on the duped (really not duped at all) nil
in your b variable, and on nil itself.

This of course is contrived, but it would be surprising behaviour. (I think)

···

On 2/16/07, Phrogz <gavin@refinery.com> wrote:

On Feb 16, 3:28 pm, "Gregory Brown" <gregory.t.br...@gmail.com> wrote:
> On 2/16/07, Robert Dober <robert.do...@gmail.com> wrote:
> > On 2/16/07, Phrogz <g...@refinery.com> wrote:

Hi,

···

In message "Re: Oppinions on RCR for dup on immutable classes" on Sun, 18 Feb 2007 01:37:19 +0900, Stefan Rusterholz <apeiros@gmx.net> 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.

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 Sun, 18 Feb 2007, Stefan Rusterholz wrote:

Yukihiro Matsumoto 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:

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

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 2/17/07, SonOfLilit <sonoflilit@gmail.com> 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?

unknown 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 Sun, 18 Feb 2007, Stefan Rusterholz wrote:

On Sun, 18 Feb 2007, Stefan Rusterholz wrote:

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

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

···

On Sun, 18 Feb 2007, Dean Wampler 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.

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

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

Interesting - and comforting - to know.
I do not have the luxury to follow more than Ruby nowadays (and I try
to find time for Smalltalk very hard, in vein so far).

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.

That just came up recently and I agree that this is kind of inelegant
(euphemistically)
Maybe that would be a reasonable CR?

> ...

Cheers
Robert

···

On 2/17/07, Dean Wampler <deanwampler@gmail.com> wrote:

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous

Hi --

···

On Sat, 17 Feb 2007, ara.t.howard@noaa.gov wrote:

On Sat, 17 Feb 2007 dblack@wobblini.net wrote:

I don't consider returning a shallow copy the same as returning self.
It's not the same object as the receiver of the "dup" message.

you may not. neither do i. nevetheless it quite true that one must
understand __completey__ the rhs in

d = obj.dup

in order to use d effectively.

I'm definitely not lobbying against understanding things :slight_smile:

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

A very good case. Enough so that I change my vote from "change dup" to
"leave things as they are".

···

On Feb 16, 4:47 pm, "Gregory Brown" <gregory.t.br...@gmail.com> wrote:

On 2/16/07, Phrogz <g...@refinery.com> wrote:
> I personally believe that returning self for symbols, fixnums, true,
> false, and nil is not bad or dangerous in any way. Can you provide a
> single example (even if contrived) where this could produce an
> unintended result? I can only come up with one myself, and it's too
> contrived for me to consider it a danger.

the only things I can think of involve singleton methods

>> def nil.foo
>> "hi there"
>> end
=> nil
>> nil.foo
=> "hi there"
>> b = nil.dup

TypeError: can't dup NilClass
        from (irb):13:in `dup'
        from (irb):13

>> def b.bar; "confusing?"; end

Imagine no error was thrown by that dup.

bar would be defined both on the duped (really not duped at all) nil
in your b variable, and on nil itself.

This of course is contrived, but it would be surprising behaviour. (I think)

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

···

On 2/17/07, Yukihiro Matsumoto <matz@ruby-lang.org> 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".