Using closures as a replacement for "class", @, and @@

Some of you might find it interesting that ruby’s closures/blocks can
be used as an alternative for defining classes/objects. It’s actually
quite simple. You just do this:

  • instead of class/def initialize, you use a function/method to define
    how to create/initialize an object of that “class” (the function
    name).
  • add methods by calling define_method w/ a block on the metaclass on
    the object that the “class” function will return.
  • local variables of the “class” function become “instance” variables
    since all of the blocks used for defining methods are closures and
    have access to them.
  • a variable outside that “class” function that is accessible can be
    used a “class variable”.
  • inheritance is easily done by starting with an object of the base
    class
  • multiple inheritance is probably best done with using a “has-a”
    relationship and delegating particular methods to particular member
    objects. You could also mixin using Object#extend.
  • calling a base class method can be done several ways: a) renaming
    the base method before redefining the derived method, b) store the
    base method in an instance variable, c) use a “has-a” relationship and
    store the base object in an instance variable - inherit/delegate or
    define each method explicitly.

All this is mostly academic. You should be able to base a complete
object-oriented language on closures.

There are a few advantages:

  • don’t need keywords for classes: class, module, self, super, etc.
  • don’t need to prefix instance/class variable with @ and @@. It is
    determined by closure scope instead.
  • don’t need a special “initialize” method. You put this
    functionality at the top-level of the “class” definition instead.
  • instance variables are completely private. You could even have base
    and derived classes with instance variables of the same name and they
    won’t collide. Of course you might consider this a disadvantage when
    you want a derived class to access an instance variable of a base
    class, but this can be done by providing methods to the instance
    variables.

Here is a simple example:

class Object
# are we ever going to get the fundamental method built-in to
Object?
def metaclass
class<<self;self;end
end
# this would be great to have by default too.
def define_method(name, &block)
self.metaclass.send(:define_method, name, &block)
end
end

conventional class

class Employee1 < String
@@id = 0
def initialize(name)
super(name)
@id = @@id
@@id += 1
@salary = 0
end
def self.id(); @@id; end
def id(); @id; end
def salary(); @salary; end
def hire(salary); @salary=salary; end
def raise(inc); @salary+=inc; end
def fire(); @salary=0;end
end

closure “class”

next_id = 0 # class variable: all Employee2 methods/closures share this
Employee2 = proc { |name|
this = String.new(name) # inherits methods from String
id = next_id # instance variable: methods/closures of this object
share this
next_id += 1
salary = 0 # instance variable: methods/closures of this object
share this
this.define_method(:id) { id }
this.define_method(:salary) { salary }
this.define_method(:hire) { |s| salary = s }
this.define_method(:fire) { salary = 0 }
this.define_method(:raise) { |inc| salary += inc }
this
}
Employee2.define_method(:id) { next_id } # class method

e1 = Employee1.new(“bob”)
e2 = Employee1.new(“john”)
e3 = Employee1.new(“sally”)

e1.hire(20)==20
e3.hire(25)==25

e1==“bob” and e1.salary==20 and e1.id==0 or raise(e1)
e2==“john” and e2.salary==0 and e2.id==1 or raise(e2)
e3==“sally” and e3.salary==25 and e3.id==2 or raise(e3)
Employee1.id==3 or raise

e1 = Employee2.call(“bob”)
e2 = Employee2.call(“john”)
e3 = Employee2.call(“sally”)

e1.hire(20)==20
e3.hire(25)==25

e1==“bob” and e1.salary==20 and e1.id==0 or raise(e1)
e2==“john” and e2.salary==0 and e2.id==1 or raise(e2)
e3==“sally” and e3.salary==25 and e3.id==2 or raise(e3)
Employee2.id==3 or raise

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs