Class: Object

Inherits:
BasicObject
Includes:
NanoKernel
Defined in:
lib/nano/object/method%21.rb,
lib/nano/object/new.rb,
lib/nano/object/copy.rb,
lib/nano/object/to_b.rb,
lib/nano/object/in%3F.rb,
lib/nano/object/val%3F.rb,
lib/nano/object/bool%3F.rb,
lib/nano/object/methods.rb,
lib/nano/object/superup.rb,
lib/nano/object/to_bool.rb,
lib/nano/object/true%3F.rb,
lib/nano/object/constant.rb,
lib/nano/object/false%3F.rb,
lib/nano/object/set_from.rb,
lib/nano/object/set_with.rb,
lib/nano/object/__class__.rb,
lib/nano/object/deep_copy.rb,
lib/nano/object/metaclass.rb,
lib/nano/object/super_send.rb,
lib/nano/object/assign_from.rb,
lib/nano/object/assign_with.rb,
lib/nano/object/with_reader.rb,
lib/nano/object/with_writer.rb,
lib/nano/object/object_class.rb,
lib/nano/object/object_hexid.rb,
lib/nano/object/super_method.rb,
lib/nano/object/special_class.rb,
lib/nano/object/with_accessor.rb,
lib/nano/object/singleton_class.rb,
lib/nano/object/generate_method_name.rb,
lib/nanosys.rb

Overview

– NOTES:

First Class Methods

I think the best solution would be using the notation
<tt>::ameth</tt>. This would require some minor changes
to Ruby, but with few backward incompatabilites if
parantheticals revert back to the actual method invocation.
Although this later stipulation means capitalized methods
would not be accessible in this way b/c they would intefere with
constant lookup. It's a trade off.

                Current           Proposed           Alternate
                ----------------- ------------------ -------------------
  Foo.Bar()     method call       method call        method call
  Foo.Bar       method call       method call        method call
  Foo.bar()     method call       method call        method call
  Foo.bar       method call       method call        method call
  Foo::Bar()    method call       method call        1st class method
  Foo::Bar      constant lookup   constant lookup    constant lookup
  Foo::bar()    method call       method call        1st class method
  Foo::bar      method call       1st class method   1st class method

Then again this dosen't address bound versus unbound.

Which do you prefer?

++

Instance Method Summary collapse

Instance Method Details

#assign_from(obj, *fields) ⇒ Object

Set setter methods and/or instance vars using a hash from another object.

class O
  attr_accessor :d
  def initialize( a, b, c, d)
    @a = a
    @@b = b
    $c = c
    d = d
  end
end
o1 = O.new(1,2,3,4)
o2 = O.new(0,0,0,0)

o2.assign_from { o1, '@a', '@@b', '$c', 'd' }
o2.instance_eval{ @a }   #=> 1
o2.instance_eval{ @@b }  #=> 2
o2.instance_eval{ $c }   #=> 3
02.d                     #=> 4

See also #assign_with.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/nano/object/assign_from.rb', line 27

def assign_from(obj, *fields)
  fields.each do |k|
    var = k.to_s
    var = var.slice(0,1) == '@' ? var : "@#{var}"
    if obj.instance_variables.include?(var)
      self.instance_variable_set( var, obj.instance_variable_get(var) )
    end
    @__atttributes__ |= var
#       else
#         self.instance_variable_set( k, obj.instance_variable_get(k) ) if obj.instance_variables.include?(k)
#         #self.send( "#{k}=", obj.send("#{k}") ) if self.respond_to?("#{k}=") && obj.respond_to?("#{k}")
#       end
  end
end

#assign_with(*args) ⇒ Object

Set setter methods and/or vars using a hash (or assoc array). #assign_with is a meta-programming method, which allows you to use a hash to do any kind of variable assignment and/or setting:

For example, assuming that there is an accessor defined as d:

assign_with { '@a'=>1, '@@b'=>2, '$c'=>3, 'd'=>4 }
@a   #=> 1
@@b  #=> 2
$c   #=> 3
d    #=> 4

Note that while the global variable is strictly unnecessary, it works for completeness sake.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/nano/object/assign_with.rb', line 19

def assign_with(*args)
  if args[0].is_a?(Hash) #or args[0].is_a?(Array)
    iv_val_pairs = args[0]
  else
    raise ArgumentError, "Hash required for assigning multiple variables" if args.length > 2
    iv_val_pairs = { args[0] => args[1] }
  end
  iv_val_pairs.each_pair do |k,v|
    if k.to_s.slice(0,2) == '@@'
      self.instance_eval %Q{ #{k} = v }
    else
      case k.to_s.slice(0,1)
      when '$'
        self.instance_eval %Q{ #{k} = v }
      when '@'
        self.instance_variable_set( k, v )
        @__atttributes__ |= k
      else
        self.instance_variable_set( "@#{k}", v )
        @__atttributes__ |= "@#{k}"
        #self.send( "#{k}=", v ) #if respond_to?("#{k}=")
      end
    end
  end
end

#bool?Boolean

Returns true is an object is class TrueClass or FalseClass, otherwise false.

true.bool?   #=> true
false.bool?  #=> true
nil.bool?    #=> false

Returns:

  • (Boolean)


17
18
19
# File 'lib/nano/object/bool%3F.rb', line 17

def bool?
  (true == self or false == self)
end

#constant(const) ⇒ Object

This is similar to Module#const_get but is accessible at all levels, and, unlike const_get, can handle module hierarchy.

constant("Fixnum")                  # -> Fixnum
constant(:Fixnum)                   # -> Fixnum

constant("Process::Sys")            # -> Process::Sys
constant("Regexp::MULTILINE")       # -> 4

require 'test/unit'
Test.constant("Unit::Assertions")   # -> Test::Unit::Assertions
Test.constant("::Test::Unit")       # -> Test::Unit


17
18
19
20
21
# File 'lib/nano/object/constant.rb', line 17

def constant(const)
  const = const.to_s.dup
  base = const.sub!(/^::/, '') ? Object : ( self.kind_of?(Module) ? self : self.class )
  const.split(/::/).inject(base){ |mod, name| mod.const_get(name) }
end

#copyObject

Anything that can be marshaled can be copied in totality. This is also commonly called a deep_copy.

"ABC".copy  #=> "ABC"


7
8
9
# File 'lib/nano/object/copy.rb', line 7

def copy
  Marshal::load(Marshal::dump(self))
end

#deep_copyObject

Anything that can be marshaled can be copied in totality. This is also just called copy.

"ABC".deep_copy  #=> "ABC"


7
8
9
# File 'lib/nano/object/deep_copy.rb', line 7

def deep_copy
  Marshal::load(Marshal::dump(self))
end

#false?Boolean

Returns true is an object is class FalseClass, otherwise false.

true.false?   #=> false
false.false?  #=> true
nil.false?    #=> false

Returns:

  • (Boolean)


17
18
19
# File 'lib/nano/object/false%3F.rb', line 17

def false?
  (false == self)
end

#generate_method_name(name = 'a') ⇒ Object

Generates a new symbol that is unique among the method names of the object. If a name argument is given, it will generate a similar name.

Class.generate_method_name( :class ) => :_clast_


10
11
12
13
14
15
16
# File 'lib/nano/object/generate_method_name.rb', line 10

def generate_method_name( name='a' )
  s = name.to_s
  while self.respond_to?( "_#{s}_" )
    s = s.succ
  end
  return :"_#{s}_"
end

#in?(other) ⇒ Boolean

Is self included in other?

5.in?(0..10)       #=> true
5.in?([0,1,2,3])   #=> false

Returns:

  • (Boolean)


7
8
9
# File 'lib/nano/object/in%3F.rb', line 7

def in?(other)
  other.include?(self)
end

#metaclassObject

Access to an object’s special singleton class.



4
5
6
# File 'lib/nano/object/metaclass.rb', line 4

def metaclass
  (class << self; self; end)
end

#method!(s) ⇒ Object

Easy access to method as objects, and they retain state!

def hello
  puts "Hello World!"
end
p method!(:hello)   #=> <Method: #hello>


38
39
40
# File 'lib/nano/object/method%21.rb', line 38

def method!(s)
  ( @__methods__ ||= {} )[s] ||= method(s)
end

#methods(*args) ⇒ Object

Returns a list of methods according to symbol(s) given.

Usable symbols include:

  • :inherited or :ancestors

  • :local or :no_ancestors

  • :public

  • :private

  • :protected

  • :singleton

  • :all

It no symbol is given then :public is assumed. Unrecognized symbols raise an error.

def test
  puts("Hello World!")
end

methods(:local)    #=> ['test']


26
27
28
29
30
31
# File 'lib/nano/object/methods.rb', line 26

def methods(*args)
  args = [ :public, :local, :ancestors ] if args.empty?
  m = self.class.instance_methods( *args )
  m |= singleton_methods if args.include?( :singleton ) or args.include?( :all )
  m
end

#newObject

Synonymous with #clone, this is an interesting method in that it promotes prototype-based Ruby. Now Classes aren’t the only things that respond to #new.

"ABC".new  => "ABC"


8
9
10
# File 'lib/nano/object/new.rb', line 8

def new
  self.clone
end

#object_hexidObject

Returns the object id as a string in hexideciaml, which is how Ruby reports them with inspect.

"ABC".object_hexid  #=> "0x402d359c"


7
8
9
# File 'lib/nano/object/object_hexid.rb', line 7

def object_hexid
  return "0x" << ('%.x' % (2*self.__id__))[1..-1]
end

#set_from(obj, *fields) ⇒ Object

Set setter methods and/or instance vars using a hash from another object.



7
8
9
10
11
# File 'lib/nano/object/set_from.rb', line 7

def set_from(obj, *fields)
  fields.each do |k|
    self.send( "#{k}=", obj.send("#{k}") )  #if self.respond_to?("#{k}=") && obj.respond_to?("#{k}")
  end
end

#set_with(*args) ⇒ Object

Set setter methods and/or vars using a hash (or assoc array).



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/nano/object/set_with.rb', line 7

def set_with(*args)
  if args.first.is_a?(Hash)  #or args[0].is_a?(Array)
    iv_val_pairs = args.first
  else
    raise ArgumentError, "Hash required for assigning multiple variables" if args.length > 2
    iv_val_pairs = { args[0] => args[1] }
  end
  iv_val_pairs.each_pair do |k,v|
    self.send( "#{k}=", v ) #if respond_to?("#{k}=")
  end
end

#singleton_classObject

Access to an object’s special singleton class.



4
5
6
# File 'lib/nano/object/singleton_class.rb', line 4

def singleton_class
  (class << self; self; end)
end

#special_classObject

Another great alias for access to an object’s special singleton meta class.



4
5
6
# File 'lib/nano/object/special_class.rb', line 4

def special_class
  (class << self; self; end)
end

#super_method(klass, meth) ⇒ Object

Returns method of a parent class bound to self.

Raises:

  • (ArgumentError)


6
7
8
9
# File 'lib/nano/object/super_method.rb', line 6

def super_method(klass, meth)
  raise ArgumentError if ! self.class.ancestors.include?(klass)
  klass.instance_method(meth).bind(self) #.call(*args)
end

#super_send(klass, meth, *args, &blk) ⇒ Object

Call parent class/module methods once bound to self.

Raises:

  • (ArgumentError)


6
7
8
9
# File 'lib/nano/object/super_send.rb', line 6

def super_send(klass, meth, *args, &blk)
  raise ArgumentError if ! self.class.ancestors.include?(klass)
  klass.instance_method(meth).bind(self).call(*args, &blk)
end

#superup(klass = self.class.superclass) ⇒ Object Also known as: supers

Returns a Functor that allows one to call any parent method directly.

class A
  def x ; 1 ; end
end

class B < A
  def x ; 2 ; end
end

class C < B
  def x ; superup(A).x ; end
end

C.new.x  #=> 1

Raises:

  • (ArgumentError)


29
30
31
32
33
34
# File 'lib/nano/object/superup.rb', line 29

def superup(klass=self.class.superclass)
  raise ArgumentError if ! self.class.ancestors.include?(klass)
  Functor.new do |meth, *args|  # &blk|
    klass.instance_method(meth).bind(self).call(*args) # ,&blk)
  end
end

#to_bObject

Boolean conversion for not being nil or false. Other classes may redefine this to suite the particular need.

"abc".to_b   #=> true
true.to_b    #=> true
false.to_b   #=> false
nil.to_b     #=> false


11
12
13
# File 'lib/nano/object/to_b.rb', line 11

def to_b
  self ? true : false
end

#to_boolObject



3
4
5
# File 'lib/nano/object/to_bool.rb', line 3

def to_bool
  return true
end

#true?Boolean

Returns true is an object is class TrueClass, otherwise false.

true.true?   #=> true
false.true?  #=> false
nil.true?    #=> false

Returns:

  • (Boolean)


17
18
19
# File 'lib/nano/object/true%3F.rb', line 17

def true?
  (true == self)
end

#val?Boolean

Tests to see if something has value. An object is considered to have value if it is not nil and responds false or nil to #empty?.

Returns:

  • (Boolean)


8
9
10
11
12
# File 'lib/nano/object/val%3F.rb', line 8

def val?
  return false if nil?
  return false if empty? if respond_to?(:empty?)
  true
end

#with_accessor(h) ⇒ Object

Takes a hash and creates (singleton) attr_accessors for each key .

with_accessor { :x => 1, :y => 2 }
@x          #=> 1
@y          #=> 2
self.x = 3
self.y = 4
self.x      #=> 3
self.y      #=> 4


16
17
18
19
# File 'lib/nano/object/with_accessor.rb', line 16

def with_accessor(h)
  (class << self ; self ; end).send( :attr_accessor, *h.keys )
  h.each { |k,v| instance_variable_set("@#{k}", v) }
end

#with_reader(h) ⇒ Object

Takes a hash and creates (singleton) attr_readers for each key.

with_reader { :x => 1, :y => 2 }
@x       #=> 1
@y       #=> 2
self.x   #=> 1
self.y   #=> 2


14
15
16
17
# File 'lib/nano/object/with_reader.rb', line 14

def with_reader(h)
  (class << self ; self ; end).send( :attr_reader, *h.keys )
  h.each { |k,v| instance_variable_set("@#{k}", v) }
end

#with_writer(h) ⇒ Object

Takes a hash and creates (singleton) attr_writers for each key.

with_writer { :x => 1, :y => 2 }
@x           #=> 1
@y           #=> 2
self.x = 3
self.y = 4
@x           #=> 3
@y           #=> 4


16
17
18
19
# File 'lib/nano/object/with_writer.rb', line 16

def with_writer(h)
  (class << self ; self ; end).send( :attr_writer, *h.keys )
  h.each { |k,v| instance_variable_set("@#{k}", v) }
end