7stud -- wrote:
> Daniel Lucraft wrote:
>> Earle Clubb wrote:
>>> The
>>> result I'm trying to achieve is the same as if I had copied the module
>>> source code and renamed the module.  
>> 
>> I think stud number 7 was onto something. How about this:
>> 
>> CommonDef = %q{
>>   def self.hello
>>     puts "hello from #{self}"
>>   end
>> }
>> 
>> module A
>>   module_eval CommonDef
>> end
>> 
>> module B
>>   module_eval CommonDef
>> end
>> 
>> A.hello
>> B.hello
>> 
>> module B
>>   def self.hello
>>     puts "different hello"
>>   end
>> end
>> 
>> A.hello
>> B.hello
>> 
>> ===>
>> 
>> hello from A
>> hello from B
>> hello from A
>> different hello
>> 
>> _______
>> 
>> Seems to work right.
>> 
>> best,
>> Dan
> 
> As far as I can tell, your code is no different than this:
> 
> module A
>   def self.hello
>     puts "hello from #{self}"
>   end
> end
> 
> module B
>   def self.hello
>     puts "hello from #{self}"
>   end
> end
> 
> A.hello
> B.hello
> 
> module B
>   def self.hello
>     puts "different hello"
>   end
> end
> 
> A.hello
> B.hello
> 
> 
> 1) You never cloned A.  All you did was create two separate modules 
> which have similar methods.
> 
> 2) Then you manually  overwrote the method in B to do something else.
> 
> I don't see how that addresses anything the op's question.  The problem 
> has to do with the fact that clone makes a shallow copy.  In other 
> words, clone copies references to objects, so you end up with two 
> references to the same object.  Therefore, a cloned object has 
> references to the same values as the original object.
> 
> However, I can't figure out a way to make a 'deep copy' where the object 
> that a reference refers to is also copied.  I tried deleting all the 
> class variables in the cloned module and then adding them back in with 
> new values--but they still refer to the same objects as the original 
> module, which is puzzling.
> 
> module A
>   @@num = 10
>   @@arr = [1, 2, 3]
> 
>   def A.get_num
>     @@num
>   end
> 
>   def A.set_num(x)
>     @@num = x
>   end
> end
> 
> puts A.get_num
> 
> new_meth = %q{
>   def B.remove(arr)
>     arr.each do |name|
>       remove_class_variable(name.to_sym)
>     end
>   end
> }
> 
> B = A.clone
> B.module_eval(new_meth)
> 
> class_vars = B.class_variables
> B.remove(class_vars)
> 
> puts "class variables in B:"
> p B.class_variables
> 
> class_vars.each do |name|
>   B.module_eval("#{name} = 0")
> end
> 
> B.set_num("hello")
> puts 'After cloning:'
> puts A.get_num
> puts B.get_num
> 
> A.set_num("goodbye")
> puts A.get_num
> puts B.get_num
> 
> --output:--
> 10
> class variables in B:
> []
> After cloning:
> hello
> hello
> goodbye
> goodbye
> 
> The Ruby Way says there is a hack to make deep copies using Marshal, but 
> it doesn't work for me:
> 
> module A
>   @@num = 10
>   @@arr = [1, 2, 3]
> 
>   def A.get_num
>     @@num
>   end
> 
>   def A.set_num(x)
>     @@num = x
>   end
> end
> 
> 
> puts A.get_num
> 
> B = Marshal.load(Marshal.dump(A))
> B.set_num(30)
> puts "After deep copying:"
> puts A.get_num
> puts B.get_num
> 
> --output:--
> 10
> After deep copying:
> 30
> 30

I'm trying a different approach than I was initially, but I get the same 
result.  Instead of cloning the module, I'm generating each copy on the 
fly.

So instead of this:
---------------
module A
  @@str = 'hello'

  def self.str
    @@str
  end

  def self.str=(s)
    @@str = s
  end

  class Test
    def self.bye
      puts "#{self}: bye"
    end
  end
end

B = A.clone

puts "A: #{A.str}"
puts "B: #{B.str}"

B.str = 'test'

puts "A: #{A.str}"
puts "B: #{B.str}"

--- output ---
A: hello
B: hello
A: test
B: test
---------------

which causes @@str in module B to change if I change it in module A, I'm 
now doing this:

---------------
def define_module
  Module.new do
    @@str = 'hello'
    def self.str
      @@str
    end
    def self.str=(s)
      @@str = s
    end
    const_set(:Test, Class.new do
      def self.bye
        puts "#{self}: bye"
      end
    end)
  end
end

A = define_module
B = define_module

puts "A: #{A.str}"
puts "B: #{B.str}"

B.str = 'test'

puts "A: #{A.str}"
puts "B: #{B.str}"

--- output ---
A: hello
B: hello
A: test
B: test
---------------

Somehow the class variables are still shared between the modules.

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