Is it considered Harmful?

Discussion in 'Ruby' started by rolo, Jun 25, 2004.

  1. I think that Matz is going to provide a much better facility for this
    sort of thing with the :pre and :post method wrappers (AOP-style
    programming). The only valuable form of object replacement, IMO, is
    replacing a proxy object with a real object.

    Austin Ziegler, Jun 28, 2004
    1. Advertisements

  2. That sounds about right to me. Aren't there two separate issues here?
    'become', to me, means "become another **object**", not "change your

    I don't even know what

    x =
    x.class = Y

    is supposed to mean. But I do understand the idea behind this:

    x =
    y =
    x.become y

    Are the two ideas really one and the same in this thread?

    Gavin Sinclair, Jun 28, 2004
    1. Advertisements

  3. rolo

    Patrick May Guest


    You're right, there was a bit of confusion. I just reviewed evil.rb,
    #become swaps instances of objects, it doesn't fiddle with the object's
    class. The two are really quite different. :)
    This is the part that I find absurd. A class isn't just a collection
    of methods (as a Module is); it's also the lifecycle of initialize.
    That's the reason I find #class= to be harmful [ruby-talk 104494]
    They shouldn't be. I certainly mixed them up. My apologies; to be
    clear, my concern is with #class= and not #become.


    Patrick May, Jun 28, 2004
  4. rolo

    Sean O'Dell Guest

    The class that created the object should have already initialized it.
    Initialization is part of object creation, usually.

    Sean O'Dell
    Sean O'Dell, Jun 28, 2004
  5. rolo

    Sean O'Dell Guest

    That's funny, because the first one makes immediate sense to me, but I'm not
    sure what the second one does.

    What happens when x becomes y? Methods are replaced?

    Sean O'Dell
    Sean O'Dell, Jun 28, 2004
  6. No, the object x points to is discarded and x points to y instead.
    Moreover, *every* pointer to x now becomes a pointer to y, making the
    statement a little more potent than

    x = y

    The only description of #become that ever made sense to me was "like
    String#replace or Array#replace, but more general". The only
    rationalisation for this feature that ever made sense to me was, as usual,
    provided by Jim Weirich, in this thread. That is, replacing a proxy with
    a "real" object. I'm pretty sure he was talking about #become, not

    Gavin Sinclair, Jun 28, 2004
  7. rolo

    ts Guest

    S> I did it, and it worked like I said it could. I didn't say Matz would accept
    S> it or want it. In fact, I know from looking at the Ruby internals it would
    S> be very hard to make totally stable, so I wouldn't want it accepted myself,
    S> not until a lot of code was bullet-proofed internally.

    S> So, I'm not sure what your point is. Are you annoyed that it worked?

    no comment

    Guy Decoux
    ts, Jun 28, 2004
  8. rolo

    vruz Guest

    This particular example you propose with files can be done with
    Aspect Oriented Programming.
    For that specific need there's this:
    by Avi Bryant and Robert Feldt.
    It's still alpha, and has been so for about two years, so I'm not
    sure if you want to use it in the real world.
    Anyway it's a nice thing to toy with.


    --- vruz
    vruz, Jun 28, 2004
  9. I think that #become is useful in ST even for changing a fixed size
    array with a bigger one.
    People may find this page interesting:
    gabriele renzi, Jun 28, 2004
  10. gabriele renzi, Jun 28, 2004
  11. rolo

    vruz Guest

    vruz, Jun 28, 2004
  12. rolo

    Patrick May Guest


    So, SomeClass is responsible for initializing an object not only for
    its own purposes, but also for Tempfile's purposes?

    How does SomeClass know that you'll want to change the object's class
    to a Tempfile, and not a Net::HTTP?

    Do you see how this absurdity is the logical outcome of your statement?


    Patrick May, Jun 28, 2004
  13. rolo

    Sean O'Dell Guest

    You can actually do it similarly by simply replacing methods you want to
    handle and removing the ones you don't. The only problem I see with that
    approach is the case when a method somewhere finds a method you didn't
    anticipate and calls it. I think AOP would be subject to that same issue.

    Sean O'Dell
    Sean O'Dell, Jun 28, 2004
  14. rolo

    Sean O'Dell Guest

    In that case, #become sounds like a better way to get pretty much the same
    effect as class=. I just wonder, though, how on earth you find every
    reference to an object, even in C extensions. I guess if the GC can walk the
    stack and find Ruby objects, it could be walked for that purpose, too.

    Sean O'Dell
    Sean O'Dell, Jun 28, 2004
  15. rolo

    Sean O'Dell Guest

    I think you're not understanding what class= does.

    All class= does is change an existing object's class. The object already
    exists; it was already initialized and is ready for use. All class= does is
    simply change the object's class. All the initialized data is still there
    with the class; still initialized. The object doesn't have to be initialized
    in any particular way. The original class doesn't have to do any extra work
    at all; none. All that happens is, the existing object's class is changed.
    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.

    Sean O'Dell
    Sean O'Dell, Jun 28, 2004
  16. 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.

    Mikael Brockman, Jun 28, 2004
  17. rolo

    Sean O'Dell Guest

    #class= can only be called on existing objects, so it can't prevent
    initialization from happening (it already happened before you can even make
    the call). The takeover class inherits an already-initialized object. I'm
    not sure how else to say that. The object is already initialized, #class=
    cannot prevent that. Both classes, the old and the new, work with an
    already-initialized object.

    Sean O'Dell
    Sean O'Dell, Jun 28, 2004
  18. So ... with your modifications, I can safely do:

    foo =
    foo.class = Tempfile
    foo.write "bar"

    It should be utterly obvious to anyone smarter than George Bush that
    this simply won't work. Tempfile must be properly initialized using
    Tempfile#new, and simply saying that foo is now a Tempfile doesn't
    actually initialize those things upon which Tempfiles methods rely.
    Yes, foo is initialized, but it's not a properly initialized Tempfile
    even though you've called it one.

    Pathological case? You bet. But simply doing #class= doesn't do the
    proper initialization. #become (or #swap, if you prefer) is far more
    useful and practical, but only in cases of type refinement (and I'm
    dubious on the value of that) or proxy replacement (and I'm
    enthusiastic about the value of that). I really don't think that the
    danger of either one of them is worth the limited value that it
    represents given that smart programming can get around the problem in
    both cases.

    Austin Ziegler, Jun 28, 2004
  19. rolo

    Sean O'Dell Guest

    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.


    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
    Sean O'Dell, Jun 28, 2004
  20. rolo

    Sean O'Dell Guest

    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?

    Sean O'Dell
    Sean O'Dell, Jun 28, 2004
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.