facets 2.8.2 → 2.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+