Un_include and un_extend

How do I un_include a module from a class/module, or un_extend a module from
an object?

Thanks.

Hi,

···

In message "Re: un_include and un_extend" on Wed, 5 Apr 2006 01:58:46 +0900, "itsme213" <itsme213@hotmail.com> writes:

How do I un_include a module from a class/module, or un_extend a module from
an object?

You can't, under the current implementation.

              matz.

Thanks. Will 2.0 allow this?

In 1.8 are there any fancy libraries or evil hacks to accomplish this?

"Yukihiro Matsumoto" <matz@ruby-lang.org> wrote in message
news:1144170103.160028.15781.nullmailer@x31.priv.netlab.jp...

···

Hi,

In message "Re: un_include and un_extend" > on Wed, 5 Apr 2006 01:58:46 +0900, "itsme213" <itsme213@hotmail.com> > writes:

>How do I un_include a module from a class/module, or un_extend a module
from
>an object?

You can't, under the current implementation.

matz.

itsme213 schrieb:

In 1.8 are there any fancy libraries or evil hacks to accomplish this?

I think it's not included in the "evil" library [1], but it shouldn't be too hard to do so. Unfortunately, I don't have much time at the moment. If you really, really need this and can't find someone else, write me again next week...

Regards,
Pit

[1] http://rubyforge.org/projects/evil

Hi,

···

In message "Re: un_include and un_extend" on Wed, 5 Apr 2006 09:03:47 +0900, "itsme213" <itsme213@hotmail.com> writes:

Thanks. Will 2.0 allow this?

No plan. Currently I have no reason to allow it.

              matz.

I'd love to change your mind about that. One reason is
Transaction::Simple. My preferred use of Transaction::Simple will not
be including it into a class, but extending an object with it like so:

  foo = "mystring"
  Transaction::Simple.start(foo) do |t_foo|
    t_foo.gsub!(/my/, "your")
    t_foo.rewind_transaction
    t_foo.gsub!(/string/, "test")
  end
  t_foo.start_transaction # I want *this* to throw an exception.

It would make certain things easier to manage in classes that use
Transaction::Simple. I understand that it wouldn't be easy, and it
would be almost impossible to automate, so perhaps only allowing it on
modules that have an #unextended method?

I think that most modules are things that you only want to add to an
object or class. But I think that there are transient things which
would benefit from this.

-austin

···

On 4/6/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

In message "Re: un_include and un_extend" > on Wed, 5 Apr 2006 09:03:47 +0900, "itsme213" <itsme213@hotmail.com> writes:

Thanks. Will 2.0 allow this?

No plan. Currently I have no reason to allow it.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Er. This last should be:

  foo # contains "mytest"
  foo.start_transaction # this should throw an exception

-austin

···

On 4/6/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/6/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
> In message "Re: un_include and un_extend" > > on Wed, 5 Apr 2006 09:03:47 +0900, "itsme213" <itsme213@hotmail.com> writes:
>> Thanks. Will 2.0 allow this?
> No plan. Currently I have no reason to allow it.

I'd love to change your mind about that. One reason is
Transaction::Simple. My preferred use of Transaction::Simple will not
be including it into a class, but extending an object with it like so:

  foo = "mystring"
  Transaction::Simple.start(foo) do |t_foo|
    t_foo.gsub!(/my/, "your")
    t_foo.rewind_transaction
    t_foo.gsub!(/string/, "test")
  end
  t_foo.start_transaction # I want *this* to throw an exception.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Hi,

···

In message "Re: un_include and un_extend" on Thu, 6 Apr 2006 21:28:46 +0900, "Austin Ziegler" <halostatue@gmail.com> writes:

I'd love to change your mind about that. One reason is
Transaction::Simple. My preferred use of Transaction::Simple will not
be including it into a class, but extending an object with it like so:

foo = "mystring"
Transaction::Simple.start(foo) do |t_foo|
   t_foo.gsub!(/my/, "your")
   t_foo.rewind_transaction
   t_foo.gsub!(/string/, "test")
end
t_foo.start_transaction # I want *this* to throw an exception.

It would make certain things easier to manage in classes that use
Transaction::Simple. I understand that it wouldn't be easy, and it
would be almost impossible to automate, so perhaps only allowing it on
modules that have an #unextended method?

Hmm, raising NoMethodError for such case sounds like bad manner for
me, since the real reason of the error is non-existence of the method,
but being out of transaction, I guess. PStore does similar thing, but
it doesn't raise NoMethodError but PStore::Error for the reason. Am I
missing something?

              matz.

Actually, as Austin mentions in a followup email, that last line was a
typo. It would actually be:

  foo.start_transaction

The idea, I'm guessing (I don't know the internals of
Transaction::Simple) is that Transaction::Simple.start(foo) extends
foo with a module which includes the #start_transaction method, then
calls foo.start_transaction with the block provided. It would be nice
if you could then unextend the module so that foo.start_transaction
once again throws NoMethodError (since it did initially) after leaving
Transaction::Simple::start.

Jacob Fugal

···

On 4/6/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

In message "Re: un_include and un_extend" > on Thu, 6 Apr 2006 21:28:46 +0900, "Austin Ziegler" <halostatue@gmail.com> writes:
>I'd love to change your mind about that. One reason is
>Transaction::Simple. My preferred use of Transaction::Simple will not
>be including it into a class, but extending an object with it like so:
>
> foo = "mystring"
> Transaction::Simple.start(foo) do |t_foo|
> t_foo.gsub!(/my/, "your")
> t_foo.rewind_transaction
> t_foo.gsub!(/string/, "test")
> end
> t_foo.start_transaction # I want *this* to throw an exception.
>
>It would make certain things easier to manage in classes that use
>Transaction::Simple. I understand that it wouldn't be easy, and it
>would be almost impossible to automate, so perhaps only allowing it on
>modules that have an #unextended method?

Hmm, raising NoMethodError for such case sounds like bad manner for
me, since the real reason of the error is non-existence of the method,
but being out of transaction, I guess. PStore does similar thing, but
it doesn't raise NoMethodError but PStore::Error for the reason. Am I
missing something?

Hi,

···

In message "Re: un_include and un_extend" on Fri, 7 Apr 2006 00:46:47 +0900, "Jacob Fugal" <lukfugl@gmail.com> writes:

Actually, as Austin mentions in a followup email, that last line was a
typo. It would actually be:

foo.start_transaction

The idea, I'm guessing (I don't know the internals of
Transaction::Simple) is that Transaction::Simple.start(foo) extends
foo with a module which includes the #start_transaction method, then
calls foo.start_transaction with the block provided. It would be nice
if you could then unextend the module so that foo.start_transaction
once again throws NoMethodError (since it did initially) after leaving
Transaction::Simple::start.

It still sounds like bad manner for the same reason. Besides it's not
thread safe. If I were designing Transaction::Simple, I'd create
t_foo as a delegation object to the original foo. But I might be
still missing something.

              matz.

That might work and I can investigate that. Ultimately, the trick with
that mode of operation is that changes to the t_foo object *must* be
reflected to the foo object, but only if the block exits without error
or an explicit #commit_transaction call is made.

The other thing that would make me happy is the ability to not have
Marshal#dump break if I have a Proc. :wink:

-austin

···

On 4/6/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

It still sounds like bad manner for the same reason. Besides it's not
thread safe. If I were designing Transaction::Simple, I'd create
t_foo as a delegation object to the original foo. But I might be
still missing something.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Theoretically YARV could archive the byte-code, alternatively the AST could be saved with ParseTree.

···

On Apr 6, 2006, at 12:16 PM, Austin Ziegler wrote:

The other thing that would make me happy is the ability to not have
Marshal#dump break if I have a Proc. :wink:

Incidentally the last time someone asked this question I wrote this code:

% cat quasiextender.rb
require 'delegate'
module QuasiExtender
   def quasi_extend(mod)
     @__quasi_extensions ||=
     @__quasi_extensions << mod
   end

   def quasi_retract(mod)
     @__quasi_extensions ||=
     @__quasi_extensions.delete_if { |ext| ext == mod }
   end

   def method_missing(name, *args, &block)
     @__quasi_extensions ||=
     meth = nil
     found_mod = nil
     @__quasi_extensions.each do |ext|
        begin
          meth = ext.instance_method(name.to_sym)
          found_mod = ext
        rescue NameError, NoMethodError
          next
        else
          break
        end
     end

     if meth.nil? # we didn't find it
        super
     else
        sneaky_class = Class.new(SimpleDelegator) {
                 include(found_mod)
        }
        sneaky_obj = sneaky_class.new(self)

        meth.bind(sneaky_obj).call(*args, &block)
     end
   end
end

It of course has various disadvantages, and you can't use it on itself :-p

···

On Apr 6, 2006, at 12:16 PM, Austin Ziegler wrote:

On 4/6/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

It still sounds like bad manner for the same reason. Besides it's not
thread safe. If I were designing Transaction::Simple, I'd create
t_foo as a delegation object to the original foo. But I might be
still missing something.

That might work and I can investigate that. Ultimately, the trick with
that mode of operation is that changes to the t_foo object *must* be
reflected to the foo object, but only if the block exits without error
or an explicit #commit_transaction call is made.

The other thing that would make me happy is the ability to not have
Marshal#dump break if I have a Proc. :wink:

-austin
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca