Is it considered Harmful?

S

Sean O'Dell

It should be utterly obvious to anyone smarter than George Bush that
this simply won't work. Tempfile must be properly initialized using

Do me a favor. I don't insert personal attacks here towards you during these
discussions, so leave them out when you're addressing me.

Sean O'Dell
 
M

Mikael Brockman

Sean O'Dell said:
Safely, yes. Usefully, no. Tempfile can't do much with just an Object
instance, and since its methods expect its own data and nothing else, it
really would just complain that it can't do anything useful.

However:

socket.class = SocketLogger

...would be a case where something useful DID happen. Assume you get socket
in a callback method of, say, an HTTP server framework. You can't figure out
why your client code isn't getting the data you think your callback method is
sending through the socket object. So, as a debugging trick, you swap out
the socket object with a SocketLogger, which still sends data through the
socket, but also logs everything sent by your method as well as the
framework, so you can see everything going out by just analyzing a logging
file. From that point on out, every method call made on the socket object
would be handled by the SocketLogger class; no calls could slip through to
the old Socket class and go unnoticed accidently.

Both #class= and #become, I think, would serve this purpose. I like #become
for its safety, but I boggle at how you would located every single reference
to an object both in Ruby and in C extensions. Also, there's the chance that
an object could #become to another class and still be assigned methods which
expect certain data to be initialized which is not, and you could still end
up with the same dangers as #class=.

Sean O'Dell

evil.rb implements #become without traversing the entire set of live
references; it simply alters the objects in place, I think.

With just #become (no class=), you can't create objects whose
#initialize is not called. It's just like swapping variables, except
all variables that point to the pointee are affected.

mikael
 
S

Sean O'Dell

Sean O'Dell said:
evil.rb implements #become without traversing the entire set of live
references; it simply alters the objects in place, I think.

With just #become (no class=), you can't create objects whose
#initialize is not called. It's just like swapping variables, except
all variables that point to the pointee are affected.

You can't do that with #class= either. You can only call #class= on objects
that exist, hence they've been initialized. The new class might not know
what to do with the object, but the object certainly has already been
initialized.

Sean O'Dell
 
H

Hal Fulton

Sean said:
You can't do that with #class= either. You can only call #class= on objects
that exist, hence they've been initialized. The new class might not know
what to do with the object, but the object certainly has already been
initialized.

You're missing his point.

If I call Array.new, I certainly get an array whose #initialize
has been called.

But if I then do arr.class = Net::HTTP, then Net:HTTP#initialize
does NOT get called (e.g., to set the host name or whatever).


Hal
 
M

Mikael Brockman

Sean O'Dell said:
Sean O'Dell said:
On Monday 28 June 2004 09:27, Austin Ziegler wrote:


You can't do that with #class= either. You can only call #class= on
objects that exist, hence they've been initialized. The new class
might not know what to do with the object, but the object certainly
has already been initialized.

Sean O'Dell

By "whose #initialize", I meant "whose current class's #initialize".

| class A
| def initialize
| @name = 'a'
| end
| end
|
| class B
| def initialize
| @name = 'b'
| end
| end
|
| a1 = A.new
| a2 = A.new
| b = B.new
|
| a1.class = B
| # a1's @name is now 'a', but its class is B
|
| a2.become b
| # a2's @name is now 'b', and its class is B

mikael
 
A

Austin Ziegler

Safely, yes. Usefully, no. Tempfile can't do much with just an Object
instance, and since its methods expect its own data and nothing else, it
really would just complain that it can't do anything useful.

No, it wouldn't work safely, and your protestations to the contrary
won't change that -- Tempfile *expects* that by time you would call
#write on an object of its class, the tempfile will be open. You have
introduced a situation, with #class=, where not only is the tempfile
not open, it simply does not exist.

You also demonstrate a fundamental misunderstanding of the difference
between #class= and #become; they are not related.

foo = Object.new
foo.class = Tempfile

is not the same as:

foo = Object.new
foot = Tempfile.new("foot")
foo.become(foot)

All references to foo now become references to foot, and foo itself is
released for garbage collection. It should really be quite obvious why
one is safer than the other.

-austin
 
R

rolo

From: Sean O'Dell [mailto:[email protected]]
A class is pretty much just a container of methods, so all you're really
doing is changing all of the object's instance methods. But the
initialize
method doesn't matter because the object already exists and
doesn't need to
be called again.
I think Class and Modules in Ruby differ here. Modules are just set of
methods but class is not. So, all that we will like to achieve by #class= ,
we should get it by including/excluding Modules.
 
F

Florian Gross

Mikael said:
I think what Patrick means is that all methods assume that their class's
initialization method has been called. Currently, it's guaranteed to be
called, since #new calls it. What you're proposing -- #class= --
removes that guarantee.

Please note that there's a case where it's not guaranteed to be called:
There's already Object#allocate which creates an Object without
initializing it.

Regards,
Florian Gross
 
F

Florian Gross

Gavin said:
I don't even know what
x = X.new
x.class = Y
is supposed to mean. But I do understand the idea behind this:

I can make up a quick example that has no real-world meaning:
irb(main):001:0> array = [1, 2, 3]
=> [1, 2, 3]
irb(main):002:0> class MyArray < Array; def reverse; sort_by {rand}; end; end
=> nil
irb(main):003:0> array.class = MyArray; array.reverse
=> [2, 1, 3]

Does it have any use in real world code? I don't know. If anybody has an
idea for a better example then please feel free to post it.
x.become y
Are the two ideas really one and the same in this thread?

I think that they are different in what they concretely do, though
similar in what they abstractly do. (They're both about changing Objects
in a way that you usually can't after their construction.)

Regards,
Florian Gross
 
S

Sean O'Dell

You're missing his point.

If I call Array.new, I certainly get an array whose #initialize
has been called.

But if I then do arr.class = Net::HTTP, then Net:HTTP#initialize
does NOT get called (e.g., to set the host name or whatever).

Ah...I see why I haven't connected with that issue now. I think of this as a
"buyer beware" issue. If you change an existing object's class, be sure you
change it to something that understands the object it is receiving. I think
even #become would have these problems. Even using include could introduce
methods to a class which didn't initialize instance data the way it expects.

Sean O'Dell
 
F

Florian Gross

Sean said:
I'm going to ask this one time, and please everyone forgive me for going
off-topic, but could you leave out the personal stuff when we're talking
about Ruby? You and Ziegler both have a habit of being very nasty with me.
Let's discuss Ruby without the personal nastiness, could we?

I think that those are one of the few persons who earned the right of
doing more critical feedback than others, because usually that criticism
is very, very true and enlightening.

I'm still against personal attacks of course, (We're the Ruby community,
we don't want to be just like the PHP and Perl communities -- we want to
be friendly -- we want to get a long -- we want to live in a better
world that is made possible by this wonderful language!) but I didn't
see one in *this* posting of ts which you are referring to.

But please, let us not argue about what is a personal nastiness and what
isn't -- if you think that my posting didn't fit in this case then it's
fine -- I just wanted to remind the community in general and for the future.

Regards,
Florian Gross
 
S

Sean O'Dell

All references to foo now become references to foot, and foo itself is
released for garbage collection. It should really be quite obvious why
one is safer than the other.

Okay, I think I understand #become now. The object is COMPLETELY replaced by
a totally different object. I do like that much better. Somewhere I got
confused by the nature of #become.

Sean O'Dell
 
S

Sean O'Dell

I think that those are one of the few persons who earned the right of
doing more critical feedback than others, because usually that criticism
is very, very true and enlightening.

I'm not sure what that means. I have been keeping an even temper with people
in here, despite the proddings. I think if I'm being level-headed with you,
I deserve the same in return. If you can't post without inserting insults
and nasty remarks, take it to private email. Keep this ML friendly and
professional.

Sean O'Dell
 
S

Sean O'Dell

When I read Guy's response, I interpreted it as calling attention
to two peoples' differing notions of what "it worked" would mean
in this context. Not as a personal attack, but rather...

Guy: It doesn't "work" because you can trivially crash Ruby with
just changing an Array's class to a Hash. etc. etc. etc.
[Guy has understood this from the start and has been saying,
ergo, the criteria for "working" has not been satisfied.]

Sean: My hack functioned the way I expected it to, therefore,
even though it's not totally stable and I wouldn't want
it accepted by matz, "it worked".

This is why--to me--what Guy wrote does not register as a personal
attack. You both have different criteria for what constitutes
"it working".

Oddly, Sean, when you are saying, "it worked like I said it could",
I am hearing Guy saying, "yes - but it doesn't work like I said it
wouldn't."

Oh no, I didn't mean it was TOTALLY stable. I just meant it appeared stable
to me and I wanted some people who knew better about the Ruby internals to
make an assessment, which is why I brought it up in ruby-core. I didn't mean
to imply it was completely safe under all circumstances, just that with some
work, it COULD be. I know myself from looking at the internals, at how many
places where code assumed the type of self, that it was likely there were
lots of nooks and crannies that did the same thing and eventually someone
would find a way to crash Ruby with the feature. I meant, *I* found it to be
stable. I ran a few quick tests and couldn't find a way to crash Ruby with
it.

In fact, I still have the feature installed here. If someone could show me
some Ruby code that makes Ruby crash with the #class= method I implemented, I
would be more than happy to retract even that much. Show me code that
crashes my #class= implementation; I already assume it can be done, now just
show me how.

Sean O'Dell
 
F

Florian Gross

Sean said:
Oh no, I didn't mean it was TOTALLY stable. I just meant it appeared stable
to me and I wanted some people who knew better about the Ruby internals to
make an assessment, which is why I brought it up in ruby-core.

You might not have noticed it, but that is exactly what ts did. And matz
once stated that if he were to be hit by a bus that he would want ts to
take over Ruby's development. If you ask me, ts has more than enough
knowledge of Ruby's internals to rightly do point out errors -- and
that's exactly what he did as far as I see the whole situation.
In fact, I still have the feature installed here. If someone could show me
some Ruby code that makes Ruby crash with the #class= method I implemented, I
would be more than happy to retract even that much. Show me code that
crashes my #class= implementation; I already assume it can be done, now just
show me how.

I haven't tested these with your implementation, but they once were
problematic in evil.rb.

Object.class = Object # ?
Class.class = Module # ?
5.class = Object # ?
obj = Time.new; require 'stringio'; obj.class = StringIO # ?

Regards,
Florian Gross
 
S

Sean O'Dell

You might not have noticed it, but that is exactly what ts did. And matz
once stated that if he were to be hit by a bus that he would want ts to
take over Ruby's development. If you ask me, ts has more than enough
knowledge of Ruby's internals to rightly do point out errors -- and
that's exactly what he did as far as I see the whole situation.

Ah, so it was insulting when I didn't accept his word outright. I see. Well,
I meant no harm; I didn't know Guy knew so much about the internals he could
make a quick call like that.
I haven't tested these with your implementation, but they once were
problematic in evil.rb.

Object.class = Object # ?
Class.class = Module # ?

These two I would protect from #class=. Object, Class, Module and any other
built-in, bootstrap-type classes I wouldn't even try #class= with.
5.class = Object # ?

This one crashes as an integer, but as a float it does not. I'm not sure how
to apply a type check to an integer.
obj = Time.new; require 'stringio'; obj.class = StringIO # ?

This one gave this error:

testclass.rb:2:in `require': No such file to load -- stringio (LoadError)
from testclass.rb:2

...which is exactly the direction I would keep developing #class= towards; to
get a simple exception.

Sean O'Dell
 
F

Florian Gross

Sean said:
Oddly, Sean, when you are saying, "it worked like I said it could",
I am hearing Guy saying, "yes - but it doesn't work like I said it
wouldn't."
[what ts did.]
Ah, so it was insulting when I didn't accept his word outright. I see. Well,
I meant no harm; I didn't know Guy knew so much about the internals he could
make a quick call like that.

It's easy to just twist a situation so that it appears different, but
not always correct. You know that I didn't say that and I can truthfully
tell you that it neither is or was what I thought.

I mean exactly what I stated and that is that ts is right -- there is a
lot of problems that you will run into when you fiddle with Ruby's
internals which is why one ought to know what he is doing.

I have learned that while being part of development of evil.rb -- of
course one can't know everything and even less so everything
immediately, but one at least has to admit that he's not all-knowing.

But if you really can't agree with me here, then I guess it is okay. In
that case I just feel a bit sorry that a common denominator could not be
found; that would make all the people who didn't even try to find one
appear in a better light than they deserve.
testclass.rb:2:in `require': No such file to load -- stringio (LoadError)
from testclass.rb:2

StringIO is part of Ruby's Standard Library. You should have it
available -- if it is not so then something might be wrong with your
Ruby installation.

Regards,
Florian Gross
 
S

Sean O'Dell

Sean said:
Oddly, Sean, when you are saying, "it worked like I said it could",
I am hearing Guy saying, "yes - but it doesn't work like I said it
wouldn't."

[what ts did.]

Ah, so it was insulting when I didn't accept his word outright. I see.
Well, I meant no harm; I didn't know Guy knew so much about the internals
he could make a quick call like that.

But if you really can't agree with me here, then I guess it is okay. In
that case I just feel a bit sorry that a common denominator could not be
found; that would make all the people who didn't even try to find one
appear in a better light than they deserve.

What are we disagreeing on? I understand that Guy knows enough about Ruby
that he can quickly determine the likelihood that #class= would ever be safe
enough for release. I'm not sure what part of what I said you feel puts me
in disagreement with you.

Sean O'Dell
 
H

Hal Fulton

Sean said:
Sean said:
Oddly, Sean, when you are saying, "it worked like I said it could",
I am hearing Guy saying, "yes - but it doesn't work like I said it
wouldn't."

[what ts did.]

Ah, so it was insulting when I didn't accept his word outright. I see.
Well, I meant no harm; I didn't know Guy knew so much about the internals
he could make a quick call like that.

But if you really can't agree with me here, then I guess it is okay. In
that case I just feel a bit sorry that a common denominator could not be
found; that would make all the people who didn't even try to find one
appear in a better light than they deserve.


What are we disagreeing on? I understand that Guy knows enough about Ruby
that he can quickly determine the likelihood that #class= would ever be safe
enough for release. I'm not sure what part of what I said you feel puts me
in disagreement with you.

He thought you were being sarcastic in the paragraph starting "Ah..."
I had to read it twice, but decided you were not.

Guy (ts) is not superhuman, of course, but I would speculate that he
knows more about Ruby internals than anyone else outside Japan (and
quite a few or nearly all in Japan).


Hal
 
A

Ara.T.Howard

Guy (ts) is not superhuman, of course

i strongly disagree with this statement hal.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
===============================================================================
 

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

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top