primitive_wrapper 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9201093aa1a6b289a8daec63a5bb81db853ac54f
4
- data.tar.gz: eb6ebb33dd2c259832b1678d24f22892b776e13d
3
+ metadata.gz: 8e2d245c1ee0f7d46c0df391fcd4165fe22095f9
4
+ data.tar.gz: b7e8d55707e1b244619154de8373a473e364278c
5
5
  SHA512:
6
- metadata.gz: 31a190053179c69be065b30386ef83e4d300b39494a04f1cbce428df7f2b2083f21105a2d682ef04ec2a98ec311517f5c9e7130875ab7d431a63f339e52d562c
7
- data.tar.gz: cd5a4c4a12b8a2bbc53d5050431cb1b6bafd55afc8febb0c914556466f0aeaf091237f4aadb1880e25124305badf3cf2f49a78abc06787ec9cd756ea52f24243
6
+ metadata.gz: 6d8791c319f2209cd5bc85dbca416b5471a751a316ad814370cc967e9f5e9f94dd9b2a4d7143a3a92d06ba8f973fbf97e7ef5d35943bbcdba5436b3f9a98d896
7
+ data.tar.gz: 079ed7917773ad0f916afca375fbddf0285328abda5691cd44cfcaa5b0eedcc786f2158a61bf876a6e6b6b5f5fff4e0818a7c0425ae8bb5f77cda5f62b14da80
data/README.md CHANGED
@@ -65,21 +65,31 @@ five.kind_of? Integer # false
65
65
  five.kind_of? Value # true
66
66
 
67
67
  5.kind_of? Integer # true
68
- 5.kind_of? Value # false
68
+ 5.kind_of? Value # false
69
+
70
+ five.type_of? Integer # true
71
+ 5.type_of? Integer # true
69
72
  ```
70
73
 
71
74
  As we can see from the above code, the Int class does not derive from Integer or anything that would appear numeric.
72
75
  Our `Int` class is simply a container which happens to have the methods of `Integer` but does not derive itself from `Integer`.
73
76
  All of these container objects derive from the Value class.
77
+ Also note the new method `#type_of` which allows us test the inner-most entity.
74
78
 
75
79
  #### Object methods added
76
80
 
77
- There are two new instance methods added to the base Object class necessary to implement this system.
81
+ There are five new instance methods added to the base Object class necessary to implement this system.
78
82
  The most important method is the `#to_wrapper` method.
79
83
  When an instance variable calls this method, one of the wrapper containers will generate a new instance.
80
84
  The one that gets picked is the one best suited for usability.
81
- The other method named `#prim_value` will return the inner container value or simply return `self` if it is not a container derived from the `Value` class.
82
- This is mostly used internally by the container objects. Below shows which objects get mapped to which containers:
85
+ We also have a test method called `#wrapped?` to see if we are dealing with the original entity or its thinly wrapped sibling.
86
+ Another method named `#prim_value` will return the inner container value or simply return `self` if it is not a container derived from the `Value` class.
87
+ This is mostly used internally by the container objects. Now that we have wrapped versions of the base elemental objects,
88
+ we need a type checking method that can work on both wrapped and unwrapped primitives: called `#type_of?`.
89
+ Also needed is a method that can duplicated a primitive or its wrapped version; this is called `#pw_copy` which works like dup.
90
+ Note that you can't call `#dup` on an Integer without raising an exception.
91
+
92
+ Below shows which objects get mapped to which containers:
83
93
 
84
94
  ```
85
95
  nil => Bit
@@ -91,20 +101,24 @@ Rational => Number
91
101
  Symbol => SymbolW
92
102
  Hash => Property
93
103
  String => Datum
104
+ Array => XArray
105
+ Range => XRange
94
106
  ```
95
107
 
96
108
  Some examples are as follows:
97
109
 
98
110
  ```ruby
99
- n = nil.to_wrapper # n.class == Bit
100
- b = true.to_wrapper # b.class == Bool
101
- y = 13.to_wrapper # y.class == Int
102
- t = 3e-9.to_wrapper # t.class == FloatW
103
- z = (1+6i).to_wrapper # z.class == Number
104
- str = "yo!".to_wrapper # str.class == Datum
105
- me = :me.to_wrapper # me.class == SymbolW
106
- prop = {}.to_wrapper # prop.class == Property
107
- aw =[1,2,3].to_wrapper # aw.class == Value ... everything else goes inside the Value container
111
+ n = nil.to_wrapper # n.class == Bit
112
+ b = true.to_wrapper # b.class == Bool
113
+ y = 13.to_wrapper # y.class == Int
114
+ t = 3e-9.to_wrapper # t.class == FloatW
115
+ z = (1+6i).to_wrapper # z.class == Number
116
+ str = "yo!".to_wrapper # str.class == Datum
117
+ me = :me.to_wrapper # me.class == SymbolW
118
+ prop = {}.to_wrapper # prop.class == Property
119
+ ary = [1,2].to_wrapper # ary.class == XArray ... X for extended functionality
120
+ ran = (3..0).to_wrapper # ran.class == XRange
121
+ aw = /[az]/.to_wrapper # aw.class == Value ... everything else goes inside the Value container
108
122
  ```
109
123
 
110
124
  The next sections will detail which objects are allowed to be contained within each container objects.
@@ -112,12 +126,11 @@ The next sections will detail which objects are allowed to be contained within e
112
126
  #### Value class container
113
127
 
114
128
  This is the base class for all the containers created by this gem. Any object or primitive type can be held in this container.
115
- To access the contents, simply call `#val`, `#prim_val`, or `#unwrap`.
129
+ To access the contents, simply call `#val`, `#prim_val`, `#unwrap`, or for non-numeric types use the tilde `~` prefix operator.
116
130
  Note that only `Value` derived objects can call `#val` while every object can call `#prim_val`.
117
131
  You can also replace the contents with the `#replace` method or the `#val=` method.
118
132
  The `Value` container has no restrictions on what it can hold. Other wrappers will raise an exception if the wrong type is added.
119
133
  The comparison binary operators `==`, and `!=` are used to compare equality and inequality; this is done on the inner contained element.
120
- Note that arrays are already containers, so there is little utility in placing it in another container.
121
134
  The value container can only contain a single object; it is like an Array object that is only allowed to hold one item.
122
135
  See the example code below:
123
136
 
@@ -153,7 +166,11 @@ The Value class has the following instance methods:
153
166
  :== # Compares equality of the inner elements
154
167
  :!= # Compares inequality of the inner elements
155
168
  :inspect # "(Value)==>data" where Value is the class name of the Value derived object, and data is #val.inspect
156
- :to_s # returns #to_s on contained entity
169
+ :to_s # returns #to_s on contained entity
170
+ :to_wrapper # returns self ... prevents wrapping a wrapped entity
171
+ :wrapped? # also on object, tests for wrapped behavior
172
+ :type_of? # also added to object, tests innermost entity or self if primitive
173
+ :inspect # string representing wrapped primitive
157
174
  ```
158
175
 
159
176
  #### Bool class container
@@ -227,6 +244,8 @@ The `#to_int` method on `Int` returns self, while `#to_i` accesses the primitive
227
244
  Most of the time if `Integer` does not recognize something it calls coerce on the foreign object (which we grabbed from Integer).
228
245
  This means that most expressions should work in whatever order you wish: if not, you will have to convert the Int object into an Integer object.
229
246
  Pretty much all expressions with Int will create a primitive Integer.
247
+ We also have new methods `#inc` and `#dec` which work like the `C/C++` post increment operators.
248
+ Prefix version methods are `#pre_inc` and `#pre_dec`.
230
249
  See the example below:
231
250
 
232
251
  ```ruby
@@ -289,13 +308,13 @@ See below:
289
308
 
290
309
  ```ruby
291
310
  # non-mutating methods taken from Symbol:
292
- # :<, :<=, :>, :>=, :[], :between?, :capitalize, :downcase, :empty?, :length, :next, :size, :succ, :swapcase, :upcase
311
+ # :<, :<=, :>, :>=, :[], :between?, :capitalize, :downcase, :empty?, :length, :next, :size, :succ, :pred, :swapcase, :upcase
293
312
 
294
313
  # non-mutating methods taken from String:
295
314
  # :append, :include?, :prepend ... actually append renamed from :<<
296
315
 
297
316
  # mutating methods of SymbolW
298
- # :[]=, :append!, :capitalize!, :downcase!, :next!, :prepend!, :replace, :succ!, :swapcase!, :upcase!
317
+ # :[]=, :append!, :capitalize!, :downcase!, :next!, :prepend!, :replace, :succ!, :pred!, :swapcase!, :upcase!
299
318
 
300
319
  # construction:
301
320
  wsym = :my_symbol.to_wrapper
@@ -379,6 +398,74 @@ abc.defined_properties! # [] ... you just zapped the entire hash after abc
379
398
  # ::reserve_property_names! [] ... adds additional reserved words
380
399
  ```
381
400
 
401
+ #### XRange class container for Range with extensions
402
+
403
+ While inheritance could have accomplished similar goals, this gem is all about wrapped objects.
404
+ Mutability would not be possible with an inherited version. Note that Range objects are not completely immutable;
405
+ `range_instance.first.upcase!` will modify the range that is defined with strings.
406
+ The `XRange` object redefines much of the behavior of `Range` with regard to ranges that descend rather than ascend.
407
+ Note that descending Range objects will return false on methods such as `#include?` and `#cover?` and will not enumerate with `#each`.
408
+ There is great utility in having a functional downward range that actually does what would naturally be expected.
409
+ This gem includes the gem `pred` which makes reverse behavior possible.
410
+ Integers and Strings use the method `#succ` within the classic `Range` to get the next sequence value.
411
+ The method `#pred` is added to to Integers and Strings to get the inverse sequence value.
412
+ The `XRange` container captures the methods of `Range` but redefines most of the methods to define reverse behavior.
413
+ Below is a list of what has changed:
414
+
415
+ ```ruby
416
+ # :reverse Range, XRange ... reverses first and last, creates a new object of same type as caller
417
+ # :reverse! XRange ... self-modified version of :reverse
418
+ # :reverse? Range, XRange ... true if descending
419
+ # :simplify Range, XRange ... converts if possible excluded to non-excluded range with same behavior
420
+ # :simplefy! XRange ... self-modified version of :simplify
421
+ # :reorder Range, XRange ... creates ascending Range or XRange
422
+ # :reorder! XRange ... self-modified version of :reorder
423
+ # :to_range Range, XRange ... accesses inner element or returns self if Range
424
+ # :to_xr Range, XRange ... creates an XRange object or returns self if XRange
425
+ # :size, :count XRange ... redefined from nil to actual size if descending were reversed
426
+ # :include? XRange ... redefined from false to behave as if reversed
427
+ # :cover? XRange ... redefined from false to behave as if reversed
428
+ # :member? XRange ... redefined from false to behave as if reversed
429
+ # :to_a XRange ... redefined from empty [] to list ordered sequence
430
+ # :max, :min XRange ... redefined from nil to return maximum/minimum range values
431
+ # :eql? :== XRange ... compares using contained entity
432
+ # :step(n) XRange ... redefined to work with descending sequences
433
+ # :reverse_step(n) XRange ... reverses sequence before stepping
434
+ # :each XRange ... redefined to work with descending sequences
435
+ # :reverse_each XRange ... reverse version of :each
436
+ # :re_range(ng) XRange ... creates new range converting negative start, end to positive given size==ng
437
+ # ... used by XArray access operators that use descending ranges.
438
+ ```
439
+
440
+ #### XArray class container for Array with extensions
441
+
442
+ This creates a wrapped `Array` with behavior that enhances the access operators of `Array`;
443
+ additionally a few new methods were added to the wrapped version.
444
+ The methods `#ssort`, `#ssort!` sort `XArray` elements using `#to_s` on each comparison.
445
+ The methods `#isort`, `#isort!` sort `XArray` elements using `#inspect` on each comparison.
446
+ The method `#to_xa` what added to `Array` as a more terse way of creating a wrapper on `Array`.
447
+ The method `#empty!` was also added. These two aforementioned methods also get included in `XArray`.
448
+ `XArray` mimics the behavior of `Array` but redefines `:[]` and `:[]=` to include lists wich comprise indexes, ranges, and arrays of indexes.
449
+ There is also behavior that defines many-to-one, one-to-many, and many-to-many operations. Note that one-to-one behavior has not changed.
450
+ An example best explains how this works:
451
+
452
+ ```ruby
453
+ ary = [2,3,5,7,11,13,17,19,23,29,31,37,41].to_xa
454
+ tst = ary[5..0,10,-1] # tst == [13, 11, 7, 5, 3, 2, 31, 41] ... note reverse range
455
+
456
+ # many-to-many
457
+ ary[4,5,1] = "a", "b", "c", "d" # ary == [2, "c", 5, 7, "a", "b", 17, 19, 23, 29, 31, 37, 41]
458
+ # note above, unused ignored
459
+
460
+ # one-to-many
461
+ ary[8..-1] = :s # ary == [2, 3, 5, 7, 11, 13, 17, 19, :s, :s, :s, :s, :s]
462
+ # note: ary.prim_value[8..-1] = :s returns this: [2, 3, 5, 7, 11, 13, 17, 19, :s] ... which is useless
463
+
464
+ # many-to-one
465
+ ary[-1] = 1,2,3 # ary == [2, "c", 5, 7, "a", "b", 17, 19, :s, :s, :s, :s, [1, 2, 3]]
466
+ ary[-2] = [:a, :b] # ary == [2, "c", 5, 7, "a", "b", 17, 19, :s, :s, :s, [:a, :b], [1, 2, 3]]
467
+ ```
468
+
382
469
  #### Customization
383
470
 
384
471
  Things should work out of the box, until they don't. This section will detail what customization is possible with what container.
@@ -475,6 +562,14 @@ Now we are left with the head-scratcher on how to decide which is the best retur
475
562
  This can be mostly a matter of taste, but we can choose custom names that convey this information. Now if you have an extension library such as used by the `gstring` gem, you have an even larger list to choose from.
476
563
  So it is left to you to decide.
477
564
 
565
+ ## Revision History
566
+ ### Version 1.0.0
567
+ * fixed wrapper inside wrapper causing stack overflow
568
+ * Documentation updates
569
+ * Added new wrappers for Range, Array as XRange and XArray
570
+ * added primitive methods
571
+ * added Value methods, and enhanced other derived wrappers
572
+
478
573
  ## Development
479
574
 
480
575
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,14 +1,24 @@
1
1
  require "primitive_wrapper/version"
2
2
  require "blockify"
3
-
3
+ require "yieldhelper" # am I using this really?
4
+ require "pred"
4
5
 
5
6
  #
6
7
  # Standard Object upgrades
7
8
  #
8
9
  class Object
10
+ def type_of?(cls)
11
+ kind_of? cls
12
+ end
13
+ def pw_copy
14
+ self.dup rescue self
15
+ end
9
16
  def prim_value
10
17
  self
11
18
  end
19
+ def wrapped?
20
+ false
21
+ end
12
22
  def to_wrapper
13
23
  return Bit.new(nil) if self.nil?
14
24
  return Bool.new(true) if self==true
@@ -19,6 +29,8 @@ class Object
19
29
  return Datum.new(self) if self.kind_of? String
20
30
  return SymbolW.new(self) if self.kind_of? Symbol
21
31
  return Property.new(self) if self.kind_of? Hash
32
+ return XArray.new(self) if self.kind_of? Array
33
+ return XRange.new(self) if self.kind_of? Range
22
34
  return Value.new(self)
23
35
  end
24
36
  end
@@ -47,6 +59,62 @@ class NilClass
47
59
  end
48
60
  end
49
61
 
62
+ class Range
63
+ def ~
64
+ self
65
+ end
66
+ end
67
+
68
+ class Array
69
+ def ~
70
+ self
71
+ end
72
+ end
73
+
74
+ class Range # if it makes sense, add methods here
75
+ def reversed?
76
+ first > last
77
+ end
78
+ def to_xr
79
+ XRange.new self
80
+ end
81
+ def reverse
82
+ if exclude_end?
83
+ (last...first)
84
+ else
85
+ (last..first)
86
+ end
87
+ end
88
+ def reorder
89
+ if exclude_end?
90
+ last < first ? (last...first) : (first...last)
91
+ else
92
+ last < first ? (last..first) : (first..last)
93
+ end
94
+ end
95
+ def reversed?
96
+ last < first
97
+ end
98
+ def simplify
99
+ if exclude_end?
100
+ return (first...last) if first==last
101
+ return (first..last.pred)
102
+ end
103
+ return (first..last)
104
+ end
105
+ end
106
+
107
+ class Array
108
+ def empty!
109
+ old = self.dup
110
+ replace []
111
+ return old
112
+ end
113
+ def to_xa
114
+ XArray.new(self)
115
+ end
116
+ end
117
+
50
118
  #
51
119
  # BASE CLASS == Value ... a wrapper for any ruby object
52
120
  #
@@ -68,6 +136,18 @@ class Value
68
136
  @value = obj
69
137
  end
70
138
 
139
+ def to_wrapper
140
+ self
141
+ end
142
+ def wrapped?
143
+ true
144
+ end
145
+ def type_of?(cls)
146
+ return true if @value.kind_of? cls
147
+ return true if self.kind_of? cls
148
+ false
149
+ end
150
+
71
151
  def ensure_valid(obj, mess = "Incompatible type")
72
152
  unless valid_type(obj)
73
153
  raise mess
@@ -111,7 +191,7 @@ class Value
111
191
  end
112
192
 
113
193
  def replace(other)
114
- @value = other if valid_type(other)
194
+ @value = other.prim_value if valid_type(other)
115
195
  end
116
196
 
117
197
  def to_s
@@ -307,10 +387,10 @@ class SymbolW < Value
307
387
  end
308
388
 
309
389
  # create non-mutate SymbolW methods
310
- bestow_symbol_methods( [:next, :succ, :[], :length, :size, :upcase, :downcase, :capitalize, :swapcase, :<, :>, :<=, :>=, :between?, :empty? ], false)
390
+ bestow_symbol_methods( [:next, :succ, :pred, :[], :length, :size, :upcase, :downcase, :capitalize, :swapcase, :<, :>, :<=, :>=, :between?, :empty? ], false)
311
391
 
312
392
  # create mutate SymbolW methods ... these will auto-bang!
313
- bestow_symbol_methods([:next, :succ, :upcase, :downcase, :capitalize, :swapcase, :succ], true)
393
+ bestow_symbol_methods([:next, :succ, :upcase, :downcase, :capitalize, :swapcase, :pred], true)
314
394
 
315
395
  # string non-mutate methods
316
396
  bestow_string_non_mutate_methods([:match, :include?], nil)
@@ -375,6 +455,14 @@ class Int < ValueAdd
375
455
  def ~
376
456
  ~@value
377
457
  end
458
+
459
+ def pre_inc
460
+ @value+=1
461
+ end
462
+
463
+ def pre_dec
464
+ @value-=1
465
+ end
378
466
  end
379
467
 
380
468
  class FloatW < ValueAdd
@@ -539,7 +627,7 @@ class Property < Value
539
627
  @hold_keys.each_pair do |key,val|
540
628
  bad[key] = @value[key]
541
629
  end
542
- return [good,bad]
630
+ return [good, bad]
543
631
  end
544
632
 
545
633
  def [](idx)
@@ -604,7 +692,400 @@ class Property < Value
604
692
  @value[key]=dflt
605
693
  end
606
694
  end
695
+ end
607
696
 
697
+ class XRange < ValueAdd
698
+ capture_base_methods(Range)
699
+ def valid_type(prm)
700
+ return true if prm.kind_of? Range
701
+ return true if prm.kind_of? XRange
702
+ false
703
+ end
704
+ def reverse!
705
+ @value = @value.reverse
706
+ self
707
+ end
708
+ def reverse
709
+ @value.reverse.to_xr
710
+ end
711
+ def simplify!
712
+ @value = @value.simplify
713
+ self
714
+ end
715
+ def reorder!
716
+ @value = @value.reorder
717
+ self
718
+ end
719
+
720
+ def simplify
721
+ @value.simplify.to_xr
722
+ end
723
+ def to_xr
724
+ self
725
+ end
726
+ def to_range # add similar to other wrappers
727
+ @value
728
+ end
729
+ def re_range(ng)
730
+ return self if ng.nil?
731
+ return self if ng <= 0
732
+ return self unless first.kind_of? Integer
733
+ t_first = first
734
+ t_last = last
735
+ if first.negative?
736
+ t_first = ng+first
737
+ end
738
+ if last.negative?
739
+ t_last = ng+last
740
+ end
741
+ if exclude_end?
742
+ XRange.new (t_first...t_last)
743
+ else
744
+ XRange.new (t_first..t_last)
745
+ end
746
+ end
747
+ def re_range!(ng)
748
+ replace re_range(ng)
749
+ end
750
+ def size # getting the wrong count ... off by 1
751
+ dirty = false
752
+ sz = @value.size
753
+ if sz.nil?
754
+ dirty = true
755
+ elsif sz==0
756
+ dirty = true
757
+ end
758
+ unless dirty
759
+ return sz
760
+ end
761
+ if first.respond_to? :lcm # Covers both Integer and Int
762
+ sz = reversed? ? @value.reverse.size : @value.size
763
+ return sz
764
+ end
765
+ range = @value.reorder
766
+ cnt = 0
767
+ # curr = range.first.dup rescue range.first
768
+ curr = range.first.pw_copy
769
+ stop = range.last
770
+ loop do
771
+ cnt += 1 # 5..5 is count of 1
772
+ break if curr==stop
773
+ curr.succ!
774
+ end
775
+ cnt -= 1 if exclude_end?
776
+ return cnt
777
+ end
778
+ def count
779
+ size
780
+ end
781
+ def include?(val) # account for reversed ordering
782
+ @value.reorder.include? val
783
+ end
784
+ def cover?(val) # means val>=start and val<=end ... different than include
785
+ @value.reorder.include? val
786
+ end
787
+ def member?(val) # same as include?
788
+ @value.reorder.include? val
789
+ end
790
+ def to_a
791
+ dat = @value.reorder.to_a
792
+ return reversed? ? dat.reverse : dat
793
+ end
794
+ def max(*n, &block)
795
+ @value.reorder.send(:max, *n, &block)
796
+ end
797
+ def min(*n, &block)
798
+ @value.reorder.send(:min, *n, &block)
799
+ end
800
+ def eql?
801
+ @value.eql? (~other)
802
+ end
803
+ def ===(other)
804
+ @value.include? other
805
+ end
806
+
807
+ def ==(other)
808
+ @value.eql? (~other)
809
+ end
810
+
811
+ def step(n=1)
812
+ n = 1 if n<= 0
813
+ return Enumerator.enumerate_yields(self, :step, n) unless block_given?
814
+ curr = first.pw_copy
815
+ if exclude_end?
816
+ if reversed?
817
+ loop do
818
+ break if curr <= last
819
+ yield curr
820
+ n.times { |t| curr = curr.pred }
821
+ end
822
+ else
823
+ loop do
824
+ break if curr >= last
825
+ yield curr
826
+ n.times { |t| curr = curr.succ }
827
+ end
828
+ end
829
+ else
830
+ if reversed?
831
+ loop do
832
+ yield curr
833
+ break if curr <= last
834
+ n.times { |t| curr = curr.pred }
835
+ end
836
+ else
837
+ loop do
838
+ yield curr
839
+ break if curr >= last
840
+ n.times { |t| curr = curr.succ }
841
+ end
842
+ end
843
+ end
844
+ end
845
+
846
+ def reverse_step(n=1)
847
+ n = 1 if n<= 0
848
+ return Enumerator.enumerate_yields(self, :reverse_step, n) unless block_given?
849
+ curr = last.pw_copy
850
+ if exclude_end?
851
+ if reversed?
852
+ loop do
853
+ break if curr >= first
854
+ yield curr
855
+ n.times { |t| curr = curr.succ }
856
+ end
857
+ else
858
+ loop do
859
+ break if curr <= first
860
+ yield curr
861
+ n.times { |t| curr = curr.pred }
862
+ end
863
+ end
864
+ else
865
+ if reversed?
866
+ loop do
867
+ yield curr
868
+ break if curr >= first
869
+ n.times { |t| curr = curr.succ }
870
+ end
871
+ else
872
+ loop do
873
+ yield curr
874
+ break if curr <= first
875
+ n.times { |t| curr = curr.pred }
876
+ end
877
+ end
878
+ end
879
+ end
880
+
881
+ def each(&block)
882
+ self.send(:step, 1, &block)
883
+ end
884
+
885
+ def reverse_each(&block)
886
+ self.send(:reverse_step, 1, &block)
887
+ end
888
+
889
+ end
890
+
891
+ module PrimitiveWrapper
892
+ def self.get_list(list, ng=nil)
893
+ rtn = []
894
+ if list.empty?
895
+ return []
896
+ elsif list.count == 1
897
+ item = list.first
898
+ if item.type_of? Range
899
+ rtn.push item.to_wrapper
900
+ else
901
+ rtn.push item
902
+ end
903
+ return rtn
904
+ end
905
+ list.each do |ii|
906
+ if(ii.type_of? Range)
907
+ ii = ii.to_wrapper
908
+ ii.re_range!(ng)
909
+ end
910
+ if ((ii.type_of? Range) || (ii.type_of? Array))
911
+ ii.each do |idx|
912
+ rtn.push idx
913
+ end
914
+ else
915
+ rtn.push ii
916
+ end
917
+ end
918
+ return rtn
919
+ end
920
+ def self.copy(dest, source, indexes)
921
+ rtn = []
922
+ if indexes == :all
923
+ if source.type_of? Array
924
+ source.count.times do |idx|
925
+ rtn.push(dest[idx]=source[idx])
926
+ end
927
+ else
928
+ dest.count.times do |idx|
929
+ rtn.push(dest[idx]=source)
930
+ end
931
+ end
932
+ else
933
+ if source.type_of? Array
934
+ ii = 0
935
+ indexes.each do |idx|
936
+ rtn.push(dest[idx]=source[ii])
937
+ ii += 1
938
+ end
939
+ else
940
+ indexes.each do |idx|
941
+ rtn.push(dest[idx]=source)
942
+ end
943
+ end
944
+ end
945
+ rtn.count <= 1 ? rtn.first : rtn
946
+ end
608
947
  end
609
948
 
610
949
 
950
+ ### need to figure out how left and right things work ...
951
+ ####
952
+ ### OK this is cool, things on the right if more than one go in one array
953
+ ### ... or a non-array if just one item
954
+
955
+ class XArray < ValueAdd
956
+ LAM_ISORT = lambda {|a,b| a.inspect <=> b.inspect }
957
+ LAM_SSORT = lambda {|a,b| a.to_s <=> b.to_s }
958
+ capture_base_methods(Array)
959
+
960
+ def initialize(obj=[])
961
+ obj = obj.prim_value
962
+ ensure_valid(obj)
963
+ @value = obj
964
+ end
965
+
966
+ def valid_type(prm)
967
+ return true if prm.kind_of? Array
968
+ return true if prm.kind_of? XArray
969
+ false
970
+ end
971
+ def isort
972
+ @value.sort &LAM_ISORT
973
+ end
974
+ def isort!
975
+ @value.sort! &LAM_ISORT
976
+ end
977
+ def ssort
978
+ @value.sort &LAM_SSORT
979
+ end
980
+ def ssort!
981
+ @value.sort! &LAM_SSORT
982
+ end
983
+ def [](*list)
984
+ list = PrimitiveWrapper::get_list(list,size)
985
+ if list.empty?
986
+ return nil
987
+ elsif list.count==1
988
+ if list.first == :all
989
+ return @value
990
+ elsif list.first.type_of? Range # get_list may pick this appart
991
+ rtn = []
992
+ list.first.to_wrapper.re_range(size).each do |idx|
993
+ rtn.push @value[idx]
994
+ end
995
+ return rtn
996
+ else
997
+ return @value[list.first]
998
+ end
999
+ end
1000
+ rtn = []
1001
+ # for now keep this here until you can justify that it is not needed
1002
+ list.each do |ii| # I don't need to do this do I ??? get_list should untangle things
1003
+ if ii.type_of? Range
1004
+ ii.to_wrapper.re_range(size).each do |idx|
1005
+ rtn.push @value[idx]
1006
+ end
1007
+ elsif ii.type_of? Array
1008
+ ii.each do |idx|
1009
+ rtn.push @value[idx]
1010
+ end
1011
+ else
1012
+ rtn.push @value[ii]
1013
+ end
1014
+ end
1015
+ return rtn
1016
+ end
1017
+ def []=(*list)
1018
+ data = list.pop
1019
+ list = PrimitiveWrapper::get_list(list,size)
1020
+ return nil if list.empty?
1021
+ if list.count==1
1022
+ if list.first.respond_to? :each
1023
+ list = list.first
1024
+ if list.type_of? Range
1025
+ list = list.to_xr.re_range(size)
1026
+ end
1027
+ end
1028
+ end
1029
+ if list.count==1
1030
+ if list.first == :all
1031
+ PrimitiveWrapper.copy(@value, data, :all)
1032
+ end
1033
+ idxs = list.first
1034
+ if (idxs.respond_to? :each)
1035
+ if idxs.type_of? Range
1036
+ idxs = idxs.to_xr.re_range(size)
1037
+ end
1038
+ idxs.each do |idx|
1039
+ @value[idx] = data
1040
+ end
1041
+ else
1042
+ @value[idxs] = data
1043
+ end
1044
+ else
1045
+ if data.type_of? Array
1046
+ data = PrimitiveWrapper::get_list(data,size)
1047
+ end
1048
+ PrimitiveWrapper.copy(@value, data, list)
1049
+ end
1050
+ end
1051
+ def delete_at(*index_list)
1052
+ return nil if index_list.empty?
1053
+ if (index_list.count==1)
1054
+ if index_list.first==:all
1055
+ self.empty!
1056
+ end
1057
+ else
1058
+ list = PrimitiveWrapper::get_list(index_list,size)
1059
+ rtn = []
1060
+ list.sort.reverse.each do |idx|
1061
+ rtn.push = @value.delete_at(idx)
1062
+ end
1063
+ return rtn
1064
+ end
1065
+ end
1066
+ def include?(*list) # replace with list of stuff
1067
+ if list.count==1
1068
+ if list.first.respond_to? :each
1069
+ list = list.first
1070
+ end
1071
+ end
1072
+ list.each do |item|
1073
+ return false unless @value.include? item
1074
+ end
1075
+ true
1076
+ end
1077
+ def include_any?(*list) # replace with list of stuff
1078
+ if list.count==1
1079
+ if list.first.respond_to? :each
1080
+ list = list.first
1081
+ end
1082
+ end
1083
+ list.each do |item|
1084
+ return true if @value.include? item
1085
+ end
1086
+ false
1087
+ end
1088
+ end
1089
+
1090
+
1091
+
@@ -1,3 +1,3 @@
1
1
  module PrimitiveWrapper
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -29,7 +29,11 @@ The `Property` object auto-methodizes the key names of the Hash.}
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ["lib"]
31
31
 
32
- spec.add_runtime_dependency 'blockify', '>= 0.1.0'
32
+ spec.required_ruby_version = '>= 2.2.0'
33
+
34
+ spec.add_runtime_dependency 'blockify', '~> 0.2', '>= 0.2.0'
35
+ spec.add_runtime_dependency 'yieldhelper', '~> 0.1', '>= 0.1.0'
36
+ spec.add_runtime_dependency 'pred', '~> 0.1', '>= 0.1.2'
33
37
 
34
38
  spec.add_development_dependency "bundler", "~> 1.11"
35
39
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,19 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primitive_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Colvin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-30 00:00:00.000000000 Z
11
+ date: 2018-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: blockify
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.2.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.2.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: yieldhelper
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.1'
17
40
  - - ">="
18
41
  - !ruby/object:Gem::Version
19
42
  version: 0.1.0
@@ -21,9 +44,32 @@ dependencies:
21
44
  prerelease: false
22
45
  version_requirements: !ruby/object:Gem::Requirement
23
46
  requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.1'
24
50
  - - ">="
25
51
  - !ruby/object:Gem::Version
26
52
  version: 0.1.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: pred
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.1'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 0.1.2
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0.1'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 0.1.2
27
73
  - !ruby/object:Gem::Dependency
28
74
  name: bundler
29
75
  requirement: !ruby/object:Gem::Requirement
@@ -129,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
175
  requirements:
130
176
  - - ">="
131
177
  - !ruby/object:Gem::Version
132
- version: '0'
178
+ version: 2.2.0
133
179
  required_rubygems_version: !ruby/object:Gem::Requirement
134
180
  requirements:
135
181
  - - ">="