Extract methods in a class to mixin?

Hello all,

I just tried to extract the methods defined in a class and make a mixin
of them. My code looked like this:

class Class

def mixin(*methods)
	klass = self
	methods.empty? and methods = klass.instance_methods(false)
	m = Module.new
	m.instance_eval do
		methods.each do |s|
			define_method(s, klass.instance_method(s))
		end
	end
	m
end

end

class A < Array
def foo; “foo”; end
def bar; “bar”; end
end
class B
end

Mixin1 = A.mixin(:foo)
class B
include Mixin1
end
p B.new.foo

Mixin2 = A.mixin
class C
include Mixin2
end
c = C.new
p c.foo
p c.bar

It failed with a type error “bind argument must be an instance of A”. I
don’t see why it must be such an instance, because I think this should
be a job for duck typing to find out if messages fail, that are sent in
the method body. So i patched eval.c to stop complaining and it worked.
Perhaps I am missing something: But is there a reason for this check or
could it be deleted in eval.c to allow this behaviour?

Index: eval.c

···

===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.531
diff -u -p -r1.531 eval.c
— eval.c 5 Sep 2003 05:07:54 -0000 1.531
+++ eval.c 8 Sep 2003 12:33:40 -0000
@@ -7438,10 +7438,6 @@ umethod_bind(method, recv)
st_lookup(RCLASS(CLASS_OF(recv))->m_tbl, data->oid, 0)) {
rb_raise(rb_eTypeError, “method `%s’ overridden”,
rb_id2name(data->oid));
}

  •   if(!rb_obj_is_kind_of(recv, data->rklass)) {
    
  •       rb_raise(rb_eTypeError, "bind argument must be an instance of %s",
    
  •                rb_class2name(data->rklass));
    
  •   }
    

    }

    method = Data_Make_Struct(rb_cMethod,struct METHOD,bm_mark,free,bound);


The whole problem with the world is that fools and fanatics are always so
certain of themselves, but wiser people so full of doubts.
– Bertand Russell

Mixin1 = A.mixin(:foo)
class B
  include Mixin1
end
p B.new.foo

Try this

   Mixin1 = Array.mixin(:=)
   class B
      include Mixin1
   end
   a = B.new
   a[12] = 24
   p a

Guy Decoux

Try this

Mixin1 = Array.mixin(:=)
class B
include Mixin1
end
a = B.new
a[12] = 24
Line 23 ^^^
p a

It doesn’t work - I’m getting the same error as before (in the unpatched
ruby version):

bash-2.05a$ ruby mixin.rb
mixin.rb:23:in `=': bind argument must be an instance of Array (TypeError)
from mixin.rb:23

The problem is that the = method remembers the class, that it was bound to
before, and a type error is raised.

···

On 2003-09-10 22:48:24 +0900, ts wrote:


The liberty of a democracy is not safe if the people tolerate the growth
of private power to a point where it becomes stronger than their
democratic State itself. That, in its essence, is Fascism – ownership of
government by an individual, by a group, or any controlling private power.
– Franklin D. Roosevelt

It doesn't work - I'm getting the same error as before (in the unpatched
ruby version):

With your *patched* version

svg% cat b.rb
#!/usr/bin/ruby -w
class Class
   def mixin(*methods)
      klass = self
      methods.empty? and methods = klass.instance_methods(false)
      m = Module.new
      m.instance_eval do
         methods.each do |s|
            define_method(s, klass.instance_method(s))
         end
      end
      m
   end
end

Mixin1 = Array.mixin(:=)
class B
   include Mixin1
end
a = B.new
a[12] = 24
p a
svg%

svg% ./ruby b.rb
b.rb:22: [BUG] Segmentation fault
ruby 1.8.0 (2003-09-03) [i686-linux]

Aborted
svg%

You still want to apply the patch ?

Guy Decoux

svg% ./ruby b.rb
b.rb:22: [BUG] Segmentation fault
ruby 1.8.0 (2003-09-03) [i686-linux]

Aborted

Oh, that isn’t really optimal. :slight_smile:

svg%
You still want to apply the patch ?

I am not sure. This probably happens because Array has some internal
magic that can’t be extracted (that easy). However, one could argue that
you have know what you are doing anyway if you try to do such fancy
stuff. If you’re afraid that it hurts you just don’t do it.

···

On 2003-09-11 18:54:15 +0900, ts wrote:


It is practically impossible to teach good programming style to students
that have had prior exposure to BASIC; as potential programmers they are
mentally mutilated beyond hope of regeneration.
– Edsger Dijkstra, How do we tell truths that might hurt?

I am not sure. This probably happens because Array has some internal
magic that can't be extracted (that easy). However, one could argue that
you have know what you are doing anyway if you try to do such fancy

What do you do with all embedded applications which run code written by
someone else ?

stuff. If you're afraid that it hurts you just don't do it.

I'm agree with you : it's best to don't apply the patch.

Guy Decoux