facets 2.8.2 → 2.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/AUTHORS +13 -11
  2. data/HISTORY.rdoc +58 -0
  3. data/lib/core/facets/array/recursive.rb +91 -0
  4. data/lib/core/facets/array/recursively.rb +2 -2
  5. data/lib/core/facets/array/traverse.rb +23 -6
  6. data/lib/core/facets/enumerable/collisions.rb +1 -0
  7. data/lib/core/facets/enumerable/commonality.rb +4 -2
  8. data/lib/core/facets/enumerable/graph.rb +37 -1
  9. data/lib/core/facets/enumerable/mash.rb +1 -39
  10. data/lib/core/facets/enumerable/recursive.rb +75 -0
  11. data/lib/core/facets/enumerable/visit.rb +30 -0
  12. data/lib/core/facets/file/ext.rb +36 -0
  13. data/lib/core/facets/hash/graph.rb +18 -0
  14. data/lib/core/facets/hash/mash.rb +1 -18
  15. data/lib/core/facets/hash/recursive.rb +180 -0
  16. data/lib/core/facets/hash/recursive_merge.rb +6 -0
  17. data/lib/core/facets/hash/recursively.rb +2 -2
  18. data/lib/core/facets/hash/to_module.rb +26 -0
  19. data/lib/core/facets/hash/to_proc.rb +2 -2
  20. data/lib/core/facets/hash/traverse.rb +19 -13
  21. data/lib/core/facets/kernel/assign.rb +63 -0
  22. data/lib/core/facets/kernel/assign_from.rb +45 -0
  23. data/lib/core/facets/kernel/dup.rb +63 -0
  24. data/lib/core/facets/kernel/instance.rb +156 -0
  25. data/lib/core/facets/kernel/instance_assign.rb +1 -22
  26. data/lib/core/facets/kernel/meta_def.rb +4 -0
  27. data/lib/core/facets/kernel/populate.rb +1 -74
  28. data/lib/core/facets/kernel/set_from.rb +2 -0
  29. data/lib/core/facets/kernel/try_dup.rb +1 -0
  30. data/lib/core/facets/module/set.rb +36 -0
  31. data/lib/core/facets/objectspace/reflect.rb +45 -0
  32. data/lib/core/facets/struct/attributes.rb +6 -2
  33. data/lib/core/facets/symbol/op_div.rb +19 -0
  34. data/lib/core/facets/to_hash.rb +12 -0
  35. data/lib/more/facets/casting_hash.rb +172 -0
  36. data/lib/more/facets/pathname.rb +36 -0
  37. data/lib/more/facets/prepend.rb +57 -0
  38. data/lib/more/facets/random.rb +19 -3
  39. data/lib/more/facets/roman.rb +46 -153
  40. data/lib/more/facets/stash.rb +148 -33
  41. data/meta/released +1 -1
  42. data/meta/version +1 -1
  43. data/test/core/array/test_recursive.rb +18 -0
  44. data/test/core/enumerable/test_recursive.rb +18 -0
  45. data/test/core/file/test_ext.rb +31 -0
  46. data/test/core/hash/test_recursive.rb +23 -0
  47. data/test/core/hash/test_to_module.rb +21 -0
  48. data/test/core/kernel/test_assign.rb +57 -0
  49. data/test/core/kernel/test_assign_from.rb +20 -0
  50. data/test/more/test_prepend.rb +28 -0
  51. data/test/more/test_random.rb +40 -4
  52. metadata +39 -10
  53. data/lib/core/facets/kernel/instance_variables.rb +0 -97
  54. data/lib/more/facets/instance_eval.rb +0 -50
  55. data/lib/more/facets/ioredirect.rb +0 -77
  56. data/lib/more/facets/plugin_manager.rb +0 -50
  57. data/test/core/kernel/test_populate.rb +0 -46
@@ -0,0 +1,45 @@
1
+ module Kernel
2
+
3
+ # Set attribute writers using like readers
4
+ # from another object.
5
+ #
6
+ # class X
7
+ # attr_accessor :a, :b
8
+ # def initialize( a, b )
9
+ # @a,@b = a,b
10
+ # end
11
+ # end
12
+ #
13
+ # obj1 = X.new(1, 2)
14
+ # obj2 = X.new
15
+ #
16
+ # obj2.assign_from(obj1)
17
+ #
18
+ # obj2.a #=> 1
19
+ # obj2.b #=> 2
20
+ #
21
+ # TODO: Should this be called #set_from ?
22
+
23
+ def assign_from(obj, *fields)
24
+ unless fields.empty?
25
+ fields.each do |k|
26
+ send( "#{k}=", obj.send("#{k}") ) #if self.respond_to?("#{k}=") && obj.respond_to?("#{k}")
27
+ end
28
+ else
29
+ setters = methods.collect { |m| m =~ /=$/ }
30
+ setters.each do |setter|
31
+ getter = setter.chomp('=')
32
+ if obj.respond_to?(getter)
33
+ send( setter, obj.send(getter) )
34
+ fields < getter
35
+ end
36
+ end
37
+ end
38
+ fields
39
+ end
40
+
41
+ # Original name for #assign_from.
42
+ alias_method :set_from, :assign_from
43
+
44
+ end
45
+
@@ -0,0 +1,63 @@
1
+ module Kernel
2
+ # Override this in a child class if it cannot be dup'ed.
3
+ #
4
+ # CREDIT: Dan Kubb (extlib)
5
+ def dup!
6
+ dup
7
+ end
8
+
9
+ # Original name for dup! as defined by extlib.
10
+ # This will eventually be deprecated. Use #dup! instead.
11
+ def try_dup
12
+ dup!
13
+ end
14
+ end
15
+
16
+ class TrueClass
17
+ # Since TrueClass is immutable it cannot be duplicated.
18
+ # For this reason #dup! returns +self+.
19
+ def dup!
20
+ self
21
+ end
22
+ end
23
+
24
+ class FalseClass
25
+ # Since FalseClass is immutable it cannot be duplicated.
26
+ # For this reason #dup! returns +self+.
27
+ def dup!
28
+ self
29
+ end
30
+ end
31
+
32
+ class NilClass
33
+ # Since NilClass is immutable it cannot be duplicated.
34
+ # For this reason #dup! returns +self+.
35
+ def dup!
36
+ self
37
+ end
38
+ end
39
+
40
+ class Numeric
41
+ # Since Numeric is immutable it cannot be duplicated.
42
+ # For this reason #dup! returns +self+.
43
+ def dup!
44
+ self
45
+ end
46
+ end
47
+
48
+ class Symbol
49
+ # Since Symbol is immutable it cannot be duplicated.
50
+ # For this reason #dup! returns +self+.
51
+ def dup!
52
+ self
53
+ end
54
+ end
55
+
56
+ #class Module
57
+ # # Since Module is immutable it cannot be duplicated.
58
+ # # For this reason #dup! returns +self+.
59
+ # def dup!
60
+ # self
61
+ # end
62
+ #end
63
+
@@ -0,0 +1,156 @@
1
+ module Kernel
2
+ INSTANCES = {}
3
+
4
+ # Returns an instance of Instance for +self+,
5
+ # which allows convenient access to an object's
6
+ # internals.
7
+
8
+ def instance
9
+ INSTANCES[self] ||= Instance.new(self)
10
+ end
11
+
12
+ end
13
+
14
+ # = Instance Class
15
+ #
16
+ # class Friend
17
+ # attr_accessor :name, :age, :phone
18
+ # def initialize(name, age, phone)
19
+ # @name, @age, @phone = name, age, phone
20
+ # end
21
+ # end
22
+ #
23
+ # f1 = Friend.new("John", 30, "555-1212")
24
+ # p f1.instance
25
+ # f1.instance.update({:name=>'Jerry'})
26
+ # p f1.instance
27
+ #
28
+ class Instance
29
+
30
+ include Enumerable
31
+
32
+ #
33
+ def initialize(delegate)
34
+ @delegate = delegate
35
+ end
36
+
37
+ #
38
+ def instance_delegate
39
+ @delegate
40
+ end
41
+
42
+ #
43
+ def each
44
+ @delegate.instance_variables.each do |name|
45
+ yield(name[1..-1].to_sym, @delegate.instance_variable_get(name))
46
+ end
47
+ end
48
+
49
+ # Return instance variables with values as a hash.
50
+ #
51
+ # class X
52
+ # def initialize(a,b)
53
+ # @a, @b = a, b
54
+ # end
55
+ # end
56
+ #
57
+ # x = X.new(1,2)
58
+ #
59
+ # x.instance.to_h #=> { :a=>1, :b=>2 }
60
+ #
61
+ def to_h(at=false)
62
+ h = {}
63
+ if at
64
+ @delegate.instance_variables.each do |name|
65
+ h[name] = @delegate.instance_variable_get(name)
66
+ end
67
+ else
68
+ each do |key, value|
69
+ h[key] = value
70
+ end
71
+ end
72
+ h
73
+ end
74
+
75
+ # TODO: Not sure if this should be used.
76
+ alias_method :to_hash, :to_h
77
+
78
+ #
79
+ def [](name)
80
+ name = atize(name)
81
+ @delegate.instance_variable_get(name)
82
+ end
83
+
84
+ #
85
+ def []=(name, value)
86
+ name = atize(name)
87
+ @delegate.instance_variable_set(name,value)
88
+ end
89
+
90
+ #
91
+ def <<(pair)
92
+ name, value = *pair
93
+ name = atize(name)
94
+ @delegate.instance_variable_set(name, value)
95
+ end
96
+
97
+ # Set instance variables given a +hash+.
98
+ #
99
+ # instance.update('@a'=>1, '@b'=>2)
100
+ # @a #=> 1
101
+ # @b #=> 2
102
+ #
103
+ # Also, +@+ sign is not neccessary.
104
+ #
105
+ # instance.update(:a=>1, :b=>2)
106
+ # @a #=> 1
107
+ # @b #=> 2
108
+ #
109
+ def update(hash)
110
+ hash.each do |pair|
111
+ self << pair
112
+ end
113
+ end
114
+
115
+ # A hold-over from the the old #instance_assign method.
116
+ alias_method :assign, :update
117
+
118
+ # Same as #instance_variables.
119
+ def variables
120
+ @delegate.instance_variables
121
+ end
122
+
123
+ # Instance vairable names as symbols.
124
+ def keys
125
+ @delegate.instance_variables.collect do |name|
126
+ name[1..-1].to_sym
127
+ end
128
+ end
129
+
130
+ # Instance variable names as strings.
131
+ def names
132
+ @delegate.instance_variables.collect do |name|
133
+ name[1..-1]
134
+ end
135
+ end
136
+
137
+ # Instance variable values.
138
+ def values
139
+ @delegate.instance_variables.collect do |name|
140
+ @delegate.instance_variable_get(name)
141
+ end
142
+ end
143
+
144
+ # Instance evaluation.
145
+ def eval(*a,&b)
146
+ @delegate.instance_eval(*a,&b)
147
+ end
148
+
149
+ private
150
+
151
+ def atize(name)
152
+ name.to_s !~ /^@/ ? "@#{name}" : name
153
+ end
154
+
155
+ end
156
+
@@ -1,33 +1,12 @@
1
1
  module Kernel
2
2
 
3
- # Return instance variable values in an array.
4
- #
5
- # class X
6
- # def initialize(a,b)
7
- # @a, @b = a, b
8
- # end
9
- # end
10
- #
11
- # x = X.new(1,2)
12
- #
13
- # x.instance_values #=> { "a"=>1, "b"=>2 }
14
- #
15
- # WARNING: #instance_values will be deprecated. Use instance_vars.to_hash instead.
16
-
17
- def instance_values
18
- instance_variables.inject({}) do |values, name|
19
- values[name[1..-1]] = instance_variable_get(name)
20
- values
21
- end
22
- end
23
-
24
3
  # Set instance variables using a hash.
25
4
  #
26
5
  # instance_assign('@a'=>1, '@b'=>2)
27
6
  # @a #=> 1
28
7
  # @b #=> 2
29
8
  #
30
- # WARNING: #instance_assign will be deprecated. Use instance_vars.update instead.
9
+ # DEPRECATE: Use instance.update instead of #instance_assign.
31
10
 
32
11
  def instance_assign(hash)
33
12
  hash.each do |k,v|
@@ -1,3 +1,5 @@
1
+ require 'facets/kernel/meta_class'
2
+
1
3
  module Kernel
2
4
 
3
5
  # Add method to a meta-class --i.e. a singleton method.
@@ -14,5 +16,7 @@ module Kernel
14
16
  end
15
17
  end
16
18
 
19
+ alias_method :metadef, :meta_def
20
+
17
21
  end
18
22
 
@@ -1,75 +1,2 @@
1
- module Kernel
2
-
3
- # Assign via accessor methods using a hash, associative
4
- # array or block.
5
- #
6
- # object.populate( :a => 1, :b => 2 )
7
- # object.populate( :a, 1, :b, 2 )
8
- # object.populate( [:a, 1], [:b, 2] )
9
- # object.populate( *[[:a, 1], [:b, 2]] )
10
- # object.populate{ |s| s.a = 1; s.b = 2 }
11
- #
12
- # These are all the same as doing:
13
- #
14
- # object.a = 1
15
- # object.b = 2
16
- #
17
- # Using an associative array instead of hash guarentees
18
- # order of assignemnt.
19
- #
20
- # Using a hash or array will not raise an error if the
21
- # accessor does not exits -- it will simply be skipped.
22
- #
23
- # (See also: instance_vars.update, which sets instance variables directly, bypassing accessor method.)
24
- #
25
- # TODO: Better name, #set_with ?
26
-
27
- def populate(data=nil) #:yield:
28
- if data
29
- data.each do |k,v|
30
- send("#{k}=", v) if respond_to?("#{k}=")
31
- end
32
- end
33
- yield(self) if block_given?
34
- self
35
- end
36
-
37
- # Set setter methods using a another object.
38
- #
39
- # class X
40
- # attr_accessor :a, :b
41
- # def initialize( a, b )
42
- # @a,@b = a,b
43
- # end
44
- # end
45
- #
46
- # obj1 = X.new( 1, 2 )
47
- # obj2 = X.new
48
- #
49
- # obj2.set_from(obj1)
50
- #
51
- # obj2.a #=> 1
52
- # obj2.b #=> 2
53
- #
54
- # TODO: populate_from(obj) ?
55
-
56
- def set_from(obj, *fields)
57
- unless fields.empty?
58
- fields.each do |k|
59
- send( "#{k}=", obj.send("#{k}") ) #if self.respond_to?("#{k}=") && obj.respond_to?("#{k}")
60
- end
61
- else
62
- setters = methods.collect { |m| m =~ /=$/ }
63
- setters.each do |setter|
64
- getter = setter.chomp('=')
65
- if obj.respond_to?(getter)
66
- send( setter, obj.send(getter) )
67
- fields < getter
68
- end
69
- end
70
- end
71
- fields
72
- end
73
-
74
- end
1
+ require 'facets/kernel/assign'
75
2
 
@@ -0,0 +1,2 @@
1
+ require 'facets/kernel/assign_from'
2
+
@@ -0,0 +1 @@
1
+ require 'facets/kernel/dup'
@@ -0,0 +1,36 @@
1
+ class Module
2
+
3
+ unless method_defined?(:set)
4
+
5
+ # Sets an option to the given value. If the value is a proc,
6
+ # the proc will be called every time the option is accessed.
7
+ #
8
+ # CREDIT: ? (Sinatra)
9
+
10
+ def set(option, value=self, &block)
11
+ raise ArgumentError if block && value != self
12
+ value = block if block
13
+ if value.kind_of?(Proc)
14
+ if value.arity == 1
15
+ yield self
16
+ else
17
+ (class << self; self; end).module_eval do
18
+ define_method(option, &value)
19
+ define_method("#{option}?"){ !!__send__(option) }
20
+ define_method("#{option}="){ |val| set(option, Proc.new{val}) }
21
+ end
22
+ end
23
+ elsif value == self
24
+ option.each{ |k,v| set(k, v) }
25
+ elsif respond_to?("#{option}=")
26
+ __send__("#{option}=", value)
27
+ else
28
+ set(option, Proc.new{value})
29
+ end
30
+ self
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,45 @@
1
+ require 'facets/functor'
2
+
3
+ class << ObjectSpace
4
+
5
+ # Reflection ensures that information about an object
6
+ # is actual according to Ruby's Kernel definitions, just
7
+ # in case such methods have been overridden.
8
+ #
9
+ # ObjectSpace.reflect(obj).id
10
+ #
11
+ #--
12
+ # There is also a global short-cut for this method to ease
13
+ # meta-programming with it.
14
+ #
15
+ # $ref[obj].id
16
+ #++
17
+ #
18
+ # Typically theis method will be used to gather the object's
19
+ # id, as in the example given, or it's class, but any Kernel
20
+ # method can be used.
21
+ #
22
+ # Care should be taken in utilizing this technique. In most
23
+ # cases it is not needed, but in certain cases is useful
24
+ # for improving the robustness of meta-programming solutions.
25
+ #
26
+ # Note that this is also equivalent to using +as(Kernel)+:
27
+ #
28
+ # obj.as(Kernel).id
29
+ #
30
+ # But obviously, in this case there is the risk that #as has
31
+ # be overridden too.
32
+ #
33
+ def reflect(obj)
34
+ Functor.new do |meth, *a, &b|
35
+ Kernel.instance_method(meth).bind(obj).call(*a, &b)
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ # TODO: Consider this "Shorcut for +ObjectSpace.reflect+."
42
+ #$ref = lambda do |obj|
43
+ # ObjectSpace.reflect(obj)
44
+ #end
45
+