nrser 0.0.25 → 0.0.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +39 -11
  3. data/lib/nrser.rb +5 -1
  4. data/lib/nrser/array.rb +10 -53
  5. data/lib/nrser/enumerable.rb +21 -0
  6. data/lib/nrser/hash.rb +13 -476
  7. data/lib/nrser/hash/bury.rb +154 -0
  8. data/lib/nrser/hash/deep_merge.rb +57 -0
  9. data/lib/nrser/hash/except_keys.rb +42 -0
  10. data/lib/nrser/hash/guess_label_key_type.rb +37 -0
  11. data/lib/nrser/hash/slice_keys.rb +41 -0
  12. data/lib/nrser/hash/stringify_keys.rb +37 -0
  13. data/lib/nrser/hash/symbolize_keys.rb +41 -0
  14. data/lib/nrser/hash/transform_keys.rb +45 -0
  15. data/lib/nrser/merge_by.rb +26 -0
  16. data/lib/nrser/message.rb +125 -0
  17. data/lib/nrser/meta/props.rb +2 -2
  18. data/lib/nrser/meta/props/prop.rb +5 -2
  19. data/lib/nrser/object.rb +5 -0
  20. data/lib/nrser/object/as_array.rb +37 -0
  21. data/lib/nrser/object/as_hash.rb +101 -0
  22. data/lib/nrser/{truthy.rb → object/truthy.rb} +0 -0
  23. data/lib/nrser/proc.rb +132 -0
  24. data/lib/nrser/refinements.rb +1 -2
  25. data/lib/nrser/refinements/array.rb +94 -5
  26. data/lib/nrser/refinements/enumerable.rb +5 -0
  27. data/lib/nrser/refinements/hash.rb +43 -6
  28. data/lib/nrser/refinements/object.rb +22 -2
  29. data/lib/nrser/refinements/symbol.rb +12 -0
  30. data/lib/nrser/refinements/tree.rb +41 -0
  31. data/lib/nrser/rspex.rb +329 -0
  32. data/lib/nrser/string.rb +3 -0
  33. data/lib/nrser/string/looks_like.rb +51 -0
  34. data/lib/nrser/temp/where.rb +52 -0
  35. data/lib/nrser/tree.rb +86 -0
  36. data/lib/nrser/tree/leaves.rb +92 -0
  37. data/lib/nrser/tree/map_leaves.rb +63 -0
  38. data/lib/nrser/tree/transform.rb +30 -0
  39. data/lib/nrser/types.rb +9 -4
  40. data/lib/nrser/types/any.rb +1 -1
  41. data/lib/nrser/types/array.rb +167 -25
  42. data/lib/nrser/types/{hash.rb → hashes.rb} +19 -5
  43. data/lib/nrser/types/in.rb +47 -0
  44. data/lib/nrser/types/is_a.rb +2 -2
  45. data/lib/nrser/types/labels.rb +49 -0
  46. data/lib/nrser/types/numbers.rb +63 -27
  47. data/lib/nrser/types/pairs.rb +109 -0
  48. data/lib/nrser/types/responds.rb +2 -3
  49. data/lib/nrser/types/strings.rb +17 -18
  50. data/lib/nrser/types/symbols.rb +39 -0
  51. data/lib/nrser/types/trees.rb +93 -0
  52. data/lib/nrser/types/tuples.rb +116 -0
  53. data/lib/nrser/types/type.rb +26 -2
  54. data/lib/nrser/version.rb +1 -1
  55. data/spec/nrser/hash/{guess_name_type_spec.rb → guess_label_key_type_spec.rb} +3 -3
  56. data/spec/nrser/hash_spec.rb +0 -20
  57. data/spec/nrser/merge_by_spec.rb +73 -0
  58. data/spec/nrser/meta/props_spec.rb +136 -43
  59. data/spec/nrser/op/message_spec.rb +62 -0
  60. data/spec/nrser/refinements/array_spec.rb +36 -0
  61. data/spec/nrser/refinements/hash_spec.rb +34 -0
  62. data/spec/nrser/string/looks_like_spec.rb +31 -0
  63. data/spec/nrser/tree/each_branch_spec.rb +82 -0
  64. data/spec/nrser/tree/leaves_spec.rb +112 -0
  65. data/spec/nrser/tree/transform_spec.rb +165 -0
  66. data/spec/nrser/types/array_spec.rb +82 -0
  67. data/spec/nrser/types/attrs_spec.rb +4 -4
  68. data/spec/nrser/types/pairs_spec.rb +41 -0
  69. data/spec/nrser/types/paths_spec.rb +3 -3
  70. data/spec/nrser/types/strings_spec.rb +66 -0
  71. data/spec/nrser/types/symbols_spec.rb +38 -0
  72. data/spec/nrser/types/tuples_spec.rb +37 -0
  73. data/spec/nrser/types_spec.rb +0 -13
  74. data/spec/spec_helper.rb +71 -22
  75. metadata +58 -10
  76. data/lib/nrser/spex.rb +0 -68
  77. data/lib/nrser/types/symbol.rb +0 -23
data/lib/nrser/string.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require_relative './string/looks_like'
2
+
1
3
  module NRSER
2
4
  class << self
3
5
  # Functions the operate on strings.
@@ -155,5 +157,6 @@ module NRSER
155
157
  end # constantize
156
158
 
157
159
  alias_method :to_const, :constantize
160
+
158
161
  end # class << self
159
162
  end # module NRSER
@@ -0,0 +1,51 @@
1
+ ##
2
+ # Functional methods that try to tell what format a string that
3
+ # is presumed to encode structural data is encoded in.
4
+ ##
5
+
6
+ # Requirements
7
+ # =======================================================================
8
+
9
+ # Stdlib
10
+ # -----------------------------------------------------------------------
11
+
12
+ # Deps
13
+ # -----------------------------------------------------------------------
14
+
15
+ # Project / Package
16
+ # -----------------------------------------------------------------------
17
+
18
+
19
+ # Definitions
20
+ # =======================================================================
21
+
22
+ module NRSER
23
+
24
+ # Constants
25
+ # =====================================================================
26
+
27
+ JSON_ARRAY_RE = /\A\s*\[.*\]\s*\z/m
28
+
29
+ # Eigenclass (Singleton Class)
30
+ # ========================================================================
31
+ #
32
+ class << self
33
+
34
+ # Test if a string looks like it might encode an array in JSON format by
35
+ # seeing if it's first non-whitespace character is `[` and last
36
+ # non-whitespace character is `]`.
37
+ #
38
+ # @param [String] string
39
+ # String to test.
40
+ #
41
+ # @return [Boolean]
42
+ # `true` if we think `string` encodes a JSON array.
43
+ #
44
+ def looks_like_json_array? string
45
+ !!( string =~ JSON_ARRAY_RE )
46
+ end # #looks_like_json_array
47
+
48
+ end # class << self (Eigenclass)
49
+
50
+ end # module NRSER
51
+
@@ -0,0 +1,52 @@
1
+
2
+
3
+ # Definitions
4
+ # =======================================================================
5
+
6
+ module NRSER
7
+
8
+ # A class to hold info about how to find a record (besides by primary key).
9
+ #
10
+ # Needs to support "template/placeholder"-type information - instructions
11
+ # about *how* to find the values to match against depending on a source
12
+ # object available later.
13
+ #
14
+ # @todo
15
+ # Not sure if this is the best name... there's already
16
+ # {NRSER::Types::Where}...
17
+ #
18
+ # Maybe this functionality has something to do with the types system?
19
+ # It seems like the placeholder stuff would be hard to integrate with
20
+ # that, but having a whole other very similar system sucks too.
21
+ #
22
+ class Where
23
+
24
+ # Constants
25
+ # ======================================================================
26
+
27
+
28
+ # Class Methods
29
+ # ======================================================================
30
+
31
+
32
+ # Attributes
33
+ # ======================================================================
34
+
35
+
36
+ # Constructor
37
+ # ======================================================================
38
+
39
+ # Instantiate a new `Where`.
40
+ def initialize
41
+
42
+ end # #initialize
43
+
44
+
45
+ # Instance Methods
46
+ # ======================================================================
47
+
48
+
49
+ end # class Where
50
+
51
+
52
+ end # module NRSER
data/lib/nrser/tree.rb ADDED
@@ -0,0 +1,86 @@
1
+ # Requirements
2
+ # =======================================================================
3
+
4
+ # Project / Package
5
+ # -----------------------------------------------------------------------
6
+ require_relative './tree/leaves'
7
+ require_relative './tree/map_leaves'
8
+ require_relative './tree/transform'
9
+
10
+
11
+ # Definitions
12
+ # =======================================================================
13
+
14
+ module NRSER
15
+
16
+ # Enumerate over the immediate "branches" of a structure that can be used
17
+ # to compose our idea of a *tree*: nested hash-like and array-like structures
18
+ # like you would get from parsing a JSON document.
19
+ #
20
+ # Written and tested against Hash and Array instances, but should work with
21
+ # anything hash-like that responds to `#each_pair` appropriately or
22
+ # array-like that responds to `#each_index` and `#each_with_index`.
23
+ #
24
+ # @note Not sure what will happen if the tree has circular references!
25
+ #
26
+ # @param [#each_pair | (#each_index & #each_with_index)] tree
27
+ # Structure representing a tree via hash-like and array-like containers.
28
+ #
29
+ # @yieldparam [Object] key
30
+ # The first yielded param is the key or index for the value branch at the
31
+ # top level of `tree`.
32
+ #
33
+ # @yieldparam [Object] value
34
+ # The second yielded param is the branch at the key or index at the top
35
+ # level of `tree`.
36
+ #
37
+ # @yieldreturn
38
+ # Ignored.
39
+ #
40
+ # @return [Enumerator]
41
+ # If no block is provided.
42
+ #
43
+ # @return [#each_pair | (#each_index & #each_with_index)]
44
+ # If a block is provided, the result of the `#each_pair` or
45
+ # `#each_with_index` call.
46
+ #
47
+ # @raise [NoMethodError]
48
+ # If `tree` does not respond to `#each_pair` or to `#each_index` and
49
+ # `#each_with_index`.
50
+ #
51
+ def self.each_branch tree, &block
52
+ if tree.respond_to? :each_pair
53
+ # Hash-like
54
+ tree.each_pair &block
55
+
56
+ elsif tree.respond_to? :each_index
57
+ # Array-like... we test for `each_index` because - unintuitively -
58
+ # `#each_with_index` is a method of {Enumerable}, meaning that {Set}
59
+ # responds to it, though sets are unordered and the values can't be
60
+ # accessed via those indexes. Hence we look for `#each_index`, which
61
+ # {Set} does not respond to.
62
+
63
+ if block.nil?
64
+ index_enumerator = tree.each_with_index
65
+
66
+ Enumerator.new( index_enumerator.size ) { |yielder|
67
+ index_enumerator.each { |value, index|
68
+ yielder.yield index, value
69
+ }
70
+ }
71
+ else
72
+ tree.each_with_index.map { |value, index|
73
+ block.call index, value
74
+ }
75
+ end
76
+
77
+ else
78
+ raise NoMethodError.new NRSER.squish <<-END
79
+ `tree` param must respond to `#each_pair` or `#each_index`,
80
+ found #{ tree.inspect }
81
+ END
82
+
83
+ end # if / else
84
+ end # .each_branch
85
+
86
+ end # module NRSER
@@ -0,0 +1,92 @@
1
+ module NRSER
2
+
3
+ # Eigenclass (Singleton Class)
4
+ # ========================================================================
5
+ #
6
+ class << self
7
+
8
+ # Create a new hash where all the values are the scalar "leaves" of the
9
+ # possibly nested `hash` param. Leaves are keyed by "key path" arrays
10
+ # representing the sequence of keys to dig that leaf out of the has param.
11
+ #
12
+ # In abstract, if `h` is the `hash` param and
13
+ #
14
+ # l = NRSER.leaves h
15
+ #
16
+ # then for each key `k` and corresponding value `v` in `l`
17
+ #
18
+ # h.dig( *k ) == v
19
+ #
20
+ # @example Simple "flat" hash
21
+ #
22
+ # NRSER.leaves( {a: 1, b: 2} )
23
+ # => {
24
+ # [:a] => 1,
25
+ # [:b] => 2,
26
+ # }
27
+ #
28
+ # @example Nested hash
29
+ #
30
+ # NRSER.leaves(
31
+ # 1 => {
32
+ # name: 'Neil',
33
+ # fav_color: 'blue',
34
+ # },
35
+ # 2 => {
36
+ # name: 'Mica',
37
+ # fav_color: 'red',
38
+ # }
39
+ # )
40
+ # # => {
41
+ # # [1, :name] => 'Neil',
42
+ # # [1, :fav_color] => 'blue',
43
+ # # [2, :name] => 'Mica',
44
+ # # [2, :fav_color] => 'red',
45
+ # # }
46
+ #
47
+ # @param [#each_pair | (#each_index & #each_with_index)] tree
48
+ #
49
+ # @return [Hash<Array, Object>]
50
+ #
51
+ def leaves tree
52
+ {}.tap { |results|
53
+ _internal_leaves tree, path: [], results: results
54
+ }
55
+ end # #leaves
56
+
57
+
58
+ private
59
+ # ========================================================================
60
+
61
+ # Internal recursive implementation for {NRSER.leaves}.
62
+ #
63
+ # @param [#each_pair | (#each_index & #each_with_index)] tree
64
+ # Tree to walk.
65
+ #
66
+ # @param [Array] path
67
+ # Key path down to `tree`.
68
+ #
69
+ # @param [Hash<Array, Object>] results
70
+ # New hash to stick results in.
71
+ #
72
+ # @return [nil]
73
+ #
74
+ def _internal_leaves tree, path:, results:
75
+ NRSER.each_branch( tree ) { |key, value|
76
+ new_path = [*path, key]
77
+
78
+ if NRSER::Types.tree.test value
79
+ _internal_leaves value, path: new_path, results: results
80
+ else
81
+ results[new_path] = value
82
+ end
83
+ }
84
+
85
+ nil
86
+ end # #_internal_leaves
87
+
88
+ # end private
89
+
90
+ end # class << self (Eigenclass)
91
+
92
+ end # module NRSER
@@ -0,0 +1,63 @@
1
+ module NRSER
2
+
3
+ # Eigenclass (Singleton Class)
4
+ # ========================================================================
5
+ #
6
+ class << self
7
+
8
+ def map_leaves tree, &block
9
+ NRSER::Types.tree.check tree
10
+
11
+ _internal_map_leaves tree, key_path: [], &block
12
+ end # #map_leaves
13
+
14
+ private
15
+ # ========================================================================
16
+
17
+ # Internal recursive implementation for {NRSER.leaves}.
18
+ #
19
+ # @param [#each_pair | (#each_index & #each_with_index)] tree
20
+ # Tree to walk.
21
+ #
22
+ # @param [Array] path
23
+ # Key path down to `tree`.
24
+ #
25
+ # @param [Hash<Array, Object>] results
26
+ # New hash to stick results in.
27
+ #
28
+ # @return [nil]
29
+ #
30
+ def _internal_map_leaves tree, key_path:, &block
31
+ NRSER::Types.match tree,
32
+ NRSER::Types.hash_like, ->( hash_like ) {
33
+ hash_like.map { |key, value|
34
+ new_key_path = [*key_path, key]
35
+
36
+ new_value = if NRSER::Types.tree.test( value )
37
+ _internal_map_leaves value, key_path: new_key_path, &block
38
+ else
39
+ block.call new_key_path, value
40
+ end
41
+
42
+ [key, new_value]
43
+ }.to_h
44
+ },
45
+
46
+ NRSER::Types.array_like, ->( array_like ) {
47
+ array_like.each_with_index.map { |value, index|
48
+ new_key_path = [*key_path, index]
49
+
50
+ if NRSER::Types.tree.test( value )
51
+ _internal_map_leaves value, key_path: new_key_path, &block
52
+ else
53
+ block.call new_key_path, value
54
+ end
55
+ }
56
+ }
57
+ end # #_internal_leaves
58
+
59
+ # end private
60
+
61
+ end # class << self (Eigenclass)
62
+
63
+ end # module NRSER
@@ -0,0 +1,30 @@
1
+ # Definitions
2
+ # =======================================================================
3
+
4
+ module NRSER
5
+
6
+ # @todo Document transform method.
7
+ #
8
+ # @param [type] arg_name
9
+ # @todo Add name param description.
10
+ #
11
+ # @return [return_type]
12
+ # @todo Document return value.
13
+ #
14
+ def self.transform tree, source
15
+ each_branch( tree ).map { |pair|
16
+ pair.map { |value|
17
+ if NRSER::Types.tree.test value
18
+ transform value, source
19
+ else
20
+ if value.is_a? Proc
21
+ value.call source
22
+ else
23
+ value
24
+ end
25
+ end
26
+ }
27
+ }.to_h
28
+ end # .transform
29
+
30
+ end # module NRSER
data/lib/nrser/types.rb CHANGED
@@ -30,6 +30,7 @@ require_relative './types/combinators'
30
30
  require_relative './types/maybe'
31
31
  require_relative './types/attrs'
32
32
  require_relative './types/responds'
33
+ require_relative './types/in'
33
34
 
34
35
 
35
36
  # Refinements
@@ -135,7 +136,7 @@ module NRSER::Types
135
136
 
136
137
  to any of types
137
138
 
138
- #{ enum.map {|type, expression| "\n #{ type.inspect }"} }
139
+ #{ enum.map {|type, expression| "\n #{ type.inspect }"}.join '' }
139
140
 
140
141
  END
141
142
  end # .match
@@ -168,7 +169,11 @@ require_relative './types/any'
168
169
  require_relative './types/booleans'
169
170
  require_relative './types/numbers'
170
171
  require_relative './types/strings'
171
- require_relative './types/symbol'
172
+ require_relative './types/symbols'
173
+ require_relative './types/labels'
172
174
  require_relative './types/array'
173
- require_relative './types/hash'
174
- require_relative './types/paths'
175
+ require_relative './types/hashes'
176
+ require_relative './types/paths'
177
+ require_relative './types/tuples'
178
+ require_relative './types/pairs'
179
+ require_relative './types/trees'
@@ -4,7 +4,7 @@ require 'nrser/types/where'
4
4
  using NRSER
5
5
 
6
6
  module NRSER::Types
7
- ANY = where(name: 'Any', from_s: ->(s) { s }) { true }.freeze
7
+ ANY = where(name: 'AnyType', from_s: ->(s) { s }) { true }.freeze
8
8
 
9
9
  # anything
10
10
  def self.any
@@ -1,60 +1,202 @@
1
- require 'nrser/refinements'
1
+ # Requirements
2
+ # =======================================================================
3
+
4
+ # Stdlib
5
+ # -----------------------------------------------------------------------
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Project / Package
11
+ # -----------------------------------------------------------------------
2
12
  require 'nrser/types/type'
3
13
  require 'nrser/types/is_a'
4
14
 
15
+
16
+ # Refinements
17
+ # =======================================================================
18
+
19
+ require 'nrser/refinements'
5
20
  using NRSER
21
+
22
+
23
+ # Declarations
24
+ # =======================================================================
25
+
26
+ module NRSER; end
27
+
28
+
29
+ # Definitions
30
+ # =======================================================================
6
31
 
7
32
  module NRSER::Types
8
- class Array < IsA
9
- SEP = /\,\s+/
33
+ class ArrayType < IsA
34
+ # Default value to split strings with in {#from_s} if the string provided
35
+ # does is not recognized as an encoding format (as of writing, JSON is
36
+ # the only format we attempt to detect).
37
+ #
38
+ # Splits
39
+ DEFAULT_SPLIT_WITH = /\,\s*/m
10
40
 
11
41
  attr_reader :item_type
12
42
 
13
- def initialize item_type = NRSER::Types::ANY, **options
43
+ def initialize split_with: DEFAULT_SPLIT_WITH, **options
14
44
  super ::Array, **options
15
- @item_type = NRSER::Types.make item_type
45
+ @split_with = split_with
16
46
  end
17
47
 
18
- def test value
19
- super(value) && if @item_type == NRSER::Types::ANY
20
- true
21
- else
22
- value.all? {|v| @item_type.test v}
23
- end
24
- end
25
48
 
26
49
  def default_name
27
- "#{ self.class.short_name }<#{ @item_type }>"
50
+ self.class.short_name
28
51
  end
29
52
 
30
- def has_from_s?
31
- @item_class.has_from_s?
53
+
54
+ # Called on an array of string items that have been split
55
+ # from a single string by {#from_s} to convert each individual item before
56
+ # {#check} is called on the value.
57
+ #
58
+ # {NRSER::Types::ArrayType} implementation is a no-op that just returns
59
+ # `items` - this method is in place for subclasses to override.
60
+ #
61
+ # @param [Array<String>] items
62
+ #
63
+ # @return [Array]
64
+ #
65
+ def items_from_strings items
66
+ items
32
67
  end
33
68
 
69
+
34
70
  def from_s s
35
- # does it looks like json?
36
- if s.start_with? '['
71
+ # Use custom {@from_s} if we have one.
72
+ return check( @from_s.call s ) unless @from_s.nil?
73
+
74
+ # Does it looks like a JSON array?
75
+ if NRSER.looks_like_json_array? s
76
+ # It does! Load it
37
77
  begin
38
- return JSON.load s
78
+ array = JSON.load( s )
39
79
  rescue
80
+ # pass - if we failed to load as JSON, it may just not be JSON, and
81
+ # we can try the split approach below.
82
+ else
83
+ # Check value and return. If we fail the check here let the error
84
+ # bubble up
85
+ return check array
40
86
  end
41
87
  end
42
88
 
43
- s.split SEP
89
+ # Split it with the splitter and check that
90
+ check items_from_strings( s.split( @split_with ) )
91
+ end
92
+
93
+ end # ArrayType
94
+
95
+
96
+ # Static instance that is satisfied by anything that is an {Array}.
97
+ ARRAY = ArrayType.new.freeze
98
+
99
+
100
+ # Type for arrays where every entry satisfies a specific type.
101
+ #
102
+ # Broken out from {ArrayType} so that {TupleType} can inherit from
103
+ # {ArrayType} and get share it's string handling functionality without
104
+ # receiving the entry type stuff (which it handles differently).
105
+ #
106
+ class ArrayOfType < ArrayType
107
+
108
+ # Attributes
109
+ # ======================================================================
110
+
111
+ # Type that all items must satisfy for an array to be a member of this
112
+ # type.
113
+ #
114
+ # @return [NRSER::Types::Type]
115
+ #
116
+ attr_reader :item_type
117
+
118
+
119
+ # Constructor
120
+ # ======================================================================
121
+
122
+ # Instantiate a new `ArrayOfType`.
123
+ def initialize item_type, **options
124
+ super **options
125
+ @item_type = NRSER::Types.make item_type
126
+ end # #initialize
127
+
128
+
129
+ # Instance Methods
130
+ # ======================================================================
131
+
132
+ def default_name
133
+ "#{ super() }<#{ @item_type }>"
134
+ end
135
+
136
+
137
+ def test value
138
+ # Check the super method first, which will test if `value` is an Array
139
+ # instance, and return `false` if it's not.
140
+ return false unless super( value )
141
+
142
+ # Otherwise test all the items
143
+ value.all? &@item_type.method( :test )
44
144
  end
45
145
 
146
+
147
+ # {ArrayOfType} can convert values from strings if it's {#item_type}
148
+ # can convert values from strings.
149
+ #
150
+ # @return [Boolean]
151
+ #
152
+ def has_from_s?
153
+ @item_type.has_from_s?
154
+ end
155
+
156
+
157
+ def items_from_strings items
158
+ items.map &@item_type.method( :from_s )
159
+ end
160
+
161
+
162
+ # @todo
163
+ # I'm not even sure why this is implemented... was it used somewhere?
164
+ #
165
+ # It doesn't seems too well thought out... seems like the reality of
166
+ # comparing types is much more complicated?
167
+ #
46
168
  def == other
47
169
  equal?(other) || (
48
170
  other.class == self.class && @item_type == other.item_type
49
171
  )
50
172
  end
51
- end # Array
173
+
174
+ end # class ArrayOfType
52
175
 
53
- # array
54
- def self.array *args
55
- Array.new *args
56
- end
57
176
 
58
- singleton_class.send :alias_method, :list, :array
177
+ # Eigenclass (Singleton Class)
178
+ # ========================================================================
179
+ #
180
+ class << self
181
+
182
+ # array
183
+ #
184
+ # @return [NRSER::Types::Type]
185
+ #
186
+ def array item_type = NRSER::NO_ARG, **options
187
+ if item_type == NRSER::NO_ARG
188
+ if options.empty?
189
+ ARRAY
190
+ else
191
+ ArrayType.new **options
192
+ end
193
+ else
194
+ ArrayOfType.new item_type, **options
195
+ end
196
+ end # #array
197
+
198
+ alias_method :list, :array
199
+
200
+ end # class << self (Eigenclass)
59
201
 
60
202
  end # NRSER::Types