Generation of initialize

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:

class A

attr_reader :a1, a2

def initialize(a1, a2)
  @a1 = a1
  @a2 = a2
end

end

I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

Any suggestions?

Thanks in advance.

You could create an attr_initializer, something like:

  module MyInitSystem
    # extend hack
    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      attr_reader :attr_initializers
      def attr_initializer(*args)
        @attr_initializers ||=
        @attr_initializers.concat(args)
        attr_reader *args
      end
    end

    def initialize(*args)
      self.class.attr_initializers.each_with_index do |a,i|
        instance_variable_set("@#{a}", args[i])
      end
    end
  end

  class A
    include MyInitSystem

    attr_initializer :a, :b
  end

Albeit, I'd use a hash to populate my object by var name.

T.

···

On Oct 13, 5:20 am, arcadiorubiogar...@gmail.com wrote:

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:

class A

attr_reader :a1, a2

def initialize(a1, a2)
  @a1 = a1
  @a2 = a2
end

end

I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

Any suggestions?

Hi

Don't know if this has been done before, but here's a quick stab I took at it:

   require 'generator'

   module InitializesWith
     def initializes_with(*params)
       define_method :initialize do |*args|
         iterator = SyncEnumerator.new(params, args)
         iterator.each do |param, arg|
           instance_variable_set "@#{param}", arg
         end
       end
     end
   end

   class Class
     include InitializesWith
   end

   class C
     attr_reader :x, :y, :z
     initializes_with :x, :y, :z
   end

   obj = C.new(1,2,3)

   obj.x # => 1
   obj.y # => 2
   obj.z # => 3

Any good?

Ashley

···

On Oct 13, 2007, at 1:20 pm, arcadiorubiogarcia@gmail.com wrote:

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:

class A

attr_reader :a1, a2

def initialize(a1, a2)
  @a1 = a1
  @a2 = a2
end

end

I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

Any suggestions?

Thanks in advance.

--
blog @ http://aviewfromafar.net/
linked-in @ Ashley Moran - United Kingdom | Professional Profile | LinkedIn
currently @ home

Are you looking for something like the following?

class A
  auto_attr_reader :a1, :a2
end

a = A.new 7,8
puts a.a1 # -> 7
puts a.a2 # -> 8

You mentioned both wanting to be able to inherit from another class
and that you don't want to define initialize, so will all of the
classes you wish to inherit from not need initialization?

···

On Oct 13, 8:19 am, arcadiorubiogar...@gmail.com wrote:

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:

class A

attr_reader :a1, a2

def initialize(a1, a2)
  @a1 = a1
  @a2 = a2
end

end

I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

It can be as simple as this.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

···

----------------------------------------------------------------

class Class
   def generate_initialize(*vars)
     define_method(:initialize) do |*args|
       vars.zip(args) do |var, arg|
         instance_variable_set("@#{var}", arg)
       end
     end
   end
end

class Foo
   generate_initialize :a, :b, :c
end

p Foo.new(1, 2, 3)

----------------------------------------------------------------

Thank you both for your replies.

Just a minor detail regarding:

   require 'generator'

   module InitializesWith
     def initializes_with(*params)
       define_method :initialize do |*args|
         iterator = SyncEnumerator.new(params, args)
         iterator.each do |param, arg|
           instance_variable_set "@#{param}", arg
         end
       end
     end
   end

   class Class
     include InitializesWith
   end

This:

   class C
     attr_reader :x, :y, :z
     initializes_with :x, :y, :z
   end

evaluates to a Proc object, due to initializes_with implementation. I
guess it would be better to return nil at the end. Just a minor
aesthetic detail as I said.

Might as well define the attrs while you're at it so you can get the
data out :slight_smile:

···

On Oct 13, 4:01 pm, Erik Veenstra <erikv...@gmail.com> wrote:

It can be as simple as this.

gegroet,
Erik V. -http://www.erikveen.dds.nl/

----------------------------------------------------------------

class Class
   def generate_initialize(*vars)
     define_method(:initialize) do |*args|
       vars.zip(args) do |var, arg|
         instance_variable_set("@#{var}", arg)
       end
     end
   end
end

class Foo
   generate_initialize :a, :b, :c
end

p Foo.new(1, 2, 3)

Return the attributes instead and you can do:

    class C
      attr_reader *initializes_with(:x, :y, :z)
    end

T.

···

On Oct 13, 7:55 am, arcadiorubiogar...@gmail.com wrote:

Thank you both for your replies.

Just a minor detail regarding:

> require 'generator'

> module InitializesWith
> def initializes_with(*params)
> define_method :initialize do |*args|
> iterator = SyncEnumerator.new(params, args)
> iterator.each do |param, arg|
> instance_variable_set "@#{param}", arg
> end
> end
> end
> end

> class Class
> include InitializesWith
> end

This:

> class C
> attr_reader :x, :y, :z
> initializes_with :x, :y, :z
> end

evaluates to a Proc object, due to initializes_with implementation. I
guess it would be better to return nil at the end. Just a minor
aesthetic detail as I said.

Hi again,

I'm trying to enhance the previous solution (shown again at the end).
I'd like to call the initialize method of the superclass from the
generated initialize. For the moment it's ok to call it without
parameters. Simply placing super inside the method definition doesn't
work. Can anyone explain me how to do it. Thanks in advance.

def initialize_with(*params)
  define_method(:initialize) do |*args|
    if args.size != params.size then
      raise ArgumentError.new("wrong number of arguments"\
        " (#{args.size} for #{params.size})")
    end
    params.zip(args) do |param, arg|
      instance_variable_set("@#{param}", arg)
    end
  end
  return params
end

Very clever :slight_smile:

···

On Oct 13, 2007, at 5:00 pm, Trans wrote:

    class C
      attr_reader *initializes_with(:x, :y, :z)
    end

--
blog @ http://aviewfromafar.net/
linked-in @ Ashley Moran - United Kingdom | Professional Profile | LinkedIn
currently @ home

Why doesn't it work?

def initialize_with(*params)
   define_method(:initialize) do |*args|
     if args.size != params.size then
       raise ArgumentError.new("wrong number of arguments"\
         " (#{args.size} for #{params.size})")
     end
     super() if defined?(super)
     params.zip(args) do |param, arg|
       instance_variable_set("@#{param}", arg)
     end
   end
   return params
end

The "()" on super clears the auto-passing of parameters.

T.

···

On Oct 31, 4:10 pm, arcadiorubiogar...@gmail.com wrote:

Hi again,

I'm trying to enhance the previous solution (shown again at the end).
I'd like to call the initialize method of the superclass from the
generated initialize. For the moment it's ok to call it without
parameters. Simply placing super inside the method definition doesn't
work. Can anyone explain me how to do it. Thanks in advance.

Trans wrote:

Hi again,

I'm trying to enhance the previous solution (shown again at the end).
I'd like to call the initialize method of the superclass from the
generated initialize. For the moment it's ok to call it without
parameters. Simply placing super inside the method definition doesn't
work. Can anyone explain me how to do it. Thanks in advance.

Why doesn't it work?

def initialize_with(*params)
   define_method(:initialize) do |*args|
     if args.size != params.size then
       raise ArgumentError.new("wrong number of arguments"\
         " (#{args.size} for #{params.size})")
     end
     super() if defined?(super)
     params.zip(args) do |param, arg|
       instance_variable_set("@#{param}", arg)
     end
   end
   return params
end

The "()" on super clears the auto-passing of parameters.

It seems to work (if this is what you meant):

module HasInitializeWith
  def initialize_with(*params)
    define_method(:initialize) do |*args|
      if args.size != params.size then
        raise ArgumentError.new("wrong number of arguments"\
          " (#{args.size} for #{params.size})")
      end
      super() if defined?(super)
      params.zip(args) do |param, arg|
        instance_variable_set("@#{param}", arg)
      end
    end
    return params
  end
end

class A
   extend HasInitializeWith
   self.initialize_with :foo
end

p A.new(3) # ==> #<A:0xb7c28cbc @foo=3>

···

On Oct 31, 4:10 pm, arcadiorubiogar...@gmail.com wrote:

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Thanks. It was the "()" on super.

···

On 31 oct, 21:53, Joel VanderWerf <vj...@path.berkeley.edu> wrote:

Trans wrote:

> On Oct 31, 4:10 pm, arcadiorubiogar...@gmail.com wrote:
>> Hi again,

>> I'm trying to enhance the previous solution (shown again at the end).
>> I'd like to call the initialize method of the superclass from the
>> generated initialize. For the moment it's ok to call it without
>> parameters. Simply placing super inside the method definition doesn't
>> work. Can anyone explain me how to do it. Thanks in advance.

> Why doesn't it work?

> def initialize_with(*params)
> define_method(:initialize) do |*args|
> if args.size != params.size then
> raise ArgumentError.new("wrong number of arguments"\
> " (#{args.size} for #{params.size})")
> end
> super() if defined?(super)
> params.zip(args) do |param, arg|
> instance_variable_set("@#{param}", arg)
> end
> end
> return params
> end

> The "()" on super clears the auto-passing of parameters.

It seems to work (if this is what you meant):

module HasInitializeWith
  def initialize_with(*params)
    define_method(:initialize) do |*args|
      if args.size != params.size then
        raise ArgumentError.new("wrong number of arguments"\
          " (#{args.size} for #{params.size})")
      end
      super() if defined?(super)
      params.zip(args) do |param, arg|
        instance_variable_set("@#{param}", arg)
      end
    end
    return params
  end
end

class A
   extend HasInitializeWith
   self.initialize_with :foo
end

p A.new(3) # ==> #<A:0xb7c28cbc @foo=3>

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407