Class (not instance) initializers

Newbie question:

Is there an equivalent to a static constructor in ruby?
something like:

class MyClass
   # want this to run before any instances of MyClass are created
   def class_initialize
     self.some_complex_initialisation
   end
end

At the moment I'm using:
class MyClass
   def initialize
     @@init = self.some_complex_initialisation if @@init.nil?
   end
end

I'd love to know if there is a more rubyesque way of doing this

Bhrgunatha.

Bhrgunatha Deva wrote:

Newbie question:

Is there an equivalent to a static constructor in ruby?
something like:

class MyClass
  # want this to run before any instances of MyClass are created
  def class_initialize
    self.some_complex_initialisation
  end
end

At the moment I'm using:
class MyClass
  def initialize
    @@init = self.some_complex_initialisation if @@init.nil?
  end
end

I'd love to know if there is a more rubyesque way of doing this

Just place your code in the class body:

class MyClass
   @class_state = complex_calculation
end

Often one needs to inform a super class of a new child. This can be done with #inherited:

class Base
   def self.inherited(cl)
     print Base, " was inherited by ", cl, "\n"
   end
end

>> class Foo < Base
>> end
Base was inherited by Foo
=> nil

Kind regards

  robert

Do you mean something like:

class InitMe
  def self.complex_init
    puts "Initializing #{self}"
  end

  complex_init
end
#(p) Initializing InitMe
# => nil

or even just:

class InitMe
  puts "Initializing #{self}"
end
#(p) Initializing InitMe
# => nil

?

···

On Tue, 2006-03-21 at 19:20 +0900, Bhrgunatha Deva wrote:

Newbie question:

Is there an equivalent to a static constructor in ruby?
something like:

class MyClass
   # want this to run before any instances of MyClass are created
   def class_initialize
     self.some_complex_initialisation
   end
end

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk

Ross Bamford wrote:

Do you mean something like:

class InitMe
  def self.complex_init
    puts "Initializing #{self}"
  end

  complex_init
end
#(p) Initializing InitMe
# => nil

I'm so dim. I didn't realise I could just call a method from inside the
class body.

Robert Klemme wrote:

Often one needs to inform a super class of a new child. This can be
done with #inherited:

class Base
  def self.inherited(cl)
    print Base, " was inherited by ", cl, "\n"
  end
end

>> class Foo < Base
>> end
Base was inherited by Foo
=> nil

Whoa, that's very neat!

Thanks.

I am creating a DSL using Ruby. A cut down version is below:

class _Box
  attr_accessor :width
      
   def initialize (&block)
                self.width = 20 # some default value
    instance_eval(&block) if block_given?
  end
end

# Helper function to avoid the DSL user having to use .new
def Box(&block)
  _Box.new(&block)
end

I want to do something like:

     Box {width = 10}

but the only way I can get it to work is

     Box {self.width = 10}

Having to prefix the ivar with self. makes the DSL look clunky and wouldn't be acceptable to my users.

Is there anyway to avoid the self.? Using {@width = 10} will work but prevents some necessary validation from taking place.

I have an alternative where width is a method:

class _Box
  def width (val = :no_param)
    if val != :no_param
      @width = val
    end
    @width
  end
end

so with this I can write

     Box {width 10}

which is acceptable from the DSL view point, but makes the getter operations more expensive. In the real version a getter operation takes about 7 statements to allow for evaluation of block if the ivar had been set to a Proc object and inheritance of values from its parent object (in a visual hierarchy). The setter operation is often only done when the object is created but the getter is done very frequently so I want to move down the route of separate setters and getters rather than combining them in the one method as an optimization.

Dave.

Dave Baldwin wrote:

I am creating a DSL using Ruby. A cut down version is below:

class _Box
    attr_accessor :width
           def initialize (&block)
               self.width = 20 # some default value
        instance_eval(&block) if block_given?
    end
end

# Helper function to avoid the DSL user having to use .new
def Box(&block)
    _Box.new(&block)
end

I want to do something like:

    Box {width = 10}

but the only way I can get it to work is

    Box {self.width = 10}

Having to prefix the ivar with self. makes the DSL look clunky and wouldn't be acceptable to my users.

Is there anyway to avoid the self.? Using {@width = 10} will work but prevents some necessary validation from taking place.

I have an alternative where width is a method:

class _Box
    def width (val = :no_param)
        if val != :no_param
            @width = val
        end
        @width
    end
end

so with this I can write

    Box {width 10}

which is acceptable from the DSL view point, but makes the getter operations more expensive. In the real version a getter operation takes about 7 statements to allow for evaluation of block if the ivar had been set to a Proc object and inheritance of values from its parent object (in a visual hierarchy). The setter operation is often only done when the object is created but the getter is done very frequently so I want to move down the route of separate setters and getters rather than combining them in the one method as an optimization.

Dave.

Good article on DSLs and addresses your question:
http://www.artima.com/rubycs/articles/ruby_as_dsl.html

Having to prefix the ivar with self. makes the DSL look clunky

I agree, though some experienced Rubyists don't see it that way.

so with this I can write

    Box {width 10}

which is acceptable from the DSL view point, but makes the getter
operations more expensive. In the real version a getter operation takes
about 7 statements to allow for evaluation of block if the ivar had been
set to a Proc object and inheritance of values from its parent object (in
a visual hierarchy). The setter operation is often only done when the
object is created but the getter is done very frequently so I want to
move down the route of separate setters and getters rather than combining
them in the one method as an optimization.

If you have some guarantees about the ordering of getters and setters, you
can dynamically (re)define the getter and setter at the instance level. The
attached worked for the case of instance variables being initialized only
once, but being read at any time (the context for this was some kind of lazy
creation of an object graph including forward references). Perhaps some bits
of it will apply to your case.

class Object
def singleton_class
  class << self; self; end
end
end

module LazyForwardRef
UNDEFINED = nil
def forward_ref(attr)
  getter = attr
  setter = (attr.to_s + '=').intern
  ivar = ('@' + attr.to_s).intern
  suspension = lambda { self.send getter }
  self.singleton_class.send :define_method, getter, lambda {
   v = instance_variable_get ivar
   if v == UNDEFINED
    suspension
   elsif v.is_a?(Proc)
    current = v.call
    self.send(setter, current) if current != v
    current
   else v
   end
  }
  self.singleton_class.send :define_method, setter, lambda {|val|
   self.instance_variable_set ivar, val
  }
end
end

require 'pp'

x = Object.new
x.extend LazyForwardRef

begin
p x.foo
rescue NoMethodError => detail
pp detail
pp [__LINE__, x, x.methods.sort - Object.instance_methods]
end

x.forward_ref(:foo)
pp [__LINE__, x, x.methods.sort - Object.instance_methods]

x.foo
pp [__LINE__, x, x.foo]

x.foo = 'Something else'
pp [__LINE__, x, x.foo]

y = Object.new
y.extend LazyForwardRef

y.forward_ref(:bar)
pp [__LINE__, y, y.methods.sort - Object.instance_methods]

z = Object.new
z.extend LazyForwardRef
z.forward_ref(:baz)

y.bar = z.baz
pp [__LINE__, x, y, z, x.foo, y.bar, z.baz, x.foo==z.baz]

x.foo = y.bar
pp [__LINE__, x, y, x.foo, y.bar]

z.baz= 10
pp [__LINE__, x, y, z]

pp [__LINE__, x.foo, y.bar, z.baz]

pp [__LINE__, x, y, z]

···

"Dave Baldwin" <dave.baldwin@3dlabs.com> wrote

here is one simple way:

     harp:~ > cat a.rb
     class OpenStruct
       alias_method "__eval__", "instance_eval"
       alias_method "__set__", "instance_variable_set"
       alias_method "__get__", "instance_variable_get"
       instance_methods.each{ |m| undef_method m unless m =~ /^__/ }
       def initialize(&block) __eval__ &block end
       def method_missing m, *a, &b
         m = m.to_s.delete "=?"
         a.size == 0 ? __get__("@#{ m }") : __set__("@#{ m }", a.shift)
       end
     end

     module Initializable
       def initialize &block
         os = OpenStruct.new &block
         attributes.each{|a| instance_variable_set "@#{ a }", os.__send__(a)}
       end
       def to_s
         require "yaml"
         attributes.inject({}){|h,a| h.update a => send(a)}.to_yaml
       end
       def attributes
         self.class::ATTRIBUTES
       end
     end

     class Box
       ATTRIBUTES = %w[ width height ]
       ATTRIBUTES.each{|a| attr a}
       include Initializable
     end

     def Box(*a, &b) Box.new(*a, &b) end

     puts Box {
       width 42
       height 42
     }

     harp:~ > ruby a.rb

···

On Tue, 21 Mar 2006, Dave Baldwin wrote:

I am creating a DSL using Ruby. A cut down version is below:

class _Box
  attr_accessor :width
      def initialize (&block)
              self.width = 20 # some default value
    instance_eval(&block) if block_given?
  end
end

# Helper function to avoid the DSL user having to use .new
def Box(&block)
  _Box.new(&block)
end

I want to do something like:

   Box {width = 10}

but the only way I can get it to work is

   Box {self.width = 10}

Having to prefix the ivar with self. makes the DSL look clunky and wouldn't be acceptable to my users.

Is there anyway to avoid the self.? Using {@width = 10} will work but prevents some necessary validation from taking place.

I have an alternative where width is a method:

class _Box
  def width (val = :no_param)
    if val != :no_param
      @width = val
    end
    @width
  end
end

so with this I can write

   Box {width 10}

which is acceptable from the DSL view point, but makes the getter operations
more expensive. In the real version a getter operation takes about 7
statements to allow for evaluation of block if the ivar had been set to a
Proc object and inheritance of values from its parent object (in a visual
hierarchy). The setter operation is often only done when the object is
created but the getter is done very frequently so I want to move down the
route of separate setters and getters rather than combining them in the one
method as an optimization.

     ---
     height: 42
     width: 42

the idea is to initialize another object, the OpenStruct in this case, and then
relay the properties. this object can have any 'slow' but convenient behaviour
your desire, leaving the Box class to have normal 'fast' attributes.

hth.

-a
--
share your knowledge. it's a way to achieve immortality.
- h.h. the 14th dali lama