5alamander / ruby-clos

clos in ruby

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ruby CLOS

Description

Combine generic-function with Ruby Object System.

Usage

Multiple method

  • use nextMethod.call to simulate (call-next-method)
  • nextMethod.call == nextMethod.call(arg1, arg2, …)
method = Clos.defGeneric "a_test_method"
method.addMethod [Integer] { |i| "integer"}
method.addMethod [Object] { "object"}

method[1] # or 'method.call(1)' or 'method.(1)'
# => "integer"

method.addMethod [Integer] { |i|
  assert_equal nextMethod.call, nextMethod.call(i)
  "integer " + nextMethod.call
}
method[233]
# => "integer object"
method[1.5]
# => "object"

Method Combination

:before/:after method

result = []
g = Clos.defGeneric "generic-function"
g.addMethod [Integer] {|i| result << i}
g.addMethod :before, [Integer] {result << :start}
g.addMethod :after, [Integer] {result << :end}
g[1] # g.call(1)
result # => [:start, 1, :end]

:around method

m1 = Clos.defGeneric "a Name"
m1.addMethod [Integer, String] { :origin }
m1.addMethod :around, [Integer, String] { :new }
m1.(1, "") # => :new

m1.addMethod :around, [Integer, String] {
  [:new].push(nextMethod.call)
}

Object init

initialize

With the native Ruby OO System

# Human -|> Hand
# Human -|> Body
module Hand
  attr_accessor :a
end

module Body
  attr_accessor :b
end

class Human
  include Hand
  include Body
  attr_accessor :v
end

Clos.init.addMethod [Human] { |h|
  h.v = "v"
}
# before init Body
Clos.init.addMethod :before, [Body] { |b|
  b.b = "b"
}
# after init Hand
Clos.init.addMethod :after, [Hand] { |h|
  h.a = "a"
}

instance = Clos.new(Human)
instance.a # => "a"
instance.b # => "b"
instance.v # => "v"

….

About

clos in ruby


Languages

Language:Ruby 100.0%