nrser 0.3.9 → 0.3.10

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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +9 -19
  3. data/lib/nrser/char/special.rb +5 -5
  4. data/lib/nrser/core_ext/array.rb +36 -13
  5. data/lib/nrser/core_ext/enumerable.rb +1 -0
  6. data/lib/nrser/core_ext/enumerable/find_map.rb +1 -1
  7. data/lib/nrser/core_ext/hash/bury.rb +3 -0
  8. data/lib/nrser/core_ext/hash/extract_values_at.rb +2 -2
  9. data/lib/nrser/core_ext/method/full_name.rb +1 -1
  10. data/lib/nrser/core_ext/module/method_objects.rb +1 -1
  11. data/lib/nrser/core_ext/module/source_locations.rb +27 -15
  12. data/lib/nrser/core_ext/object/lazy_var.rb +1 -1
  13. data/lib/nrser/core_ext/pathname.rb +67 -12
  14. data/lib/nrser/core_ext/pathname/subpath.rb +86 -0
  15. data/lib/nrser/core_ext/string.rb +28 -1
  16. data/lib/nrser/core_ext/symbol.rb +11 -12
  17. data/lib/nrser/errors/README.md +154 -0
  18. data/lib/nrser/errors/attr_error.rb +146 -53
  19. data/lib/nrser/errors/count_error.rb +61 -12
  20. data/lib/nrser/errors/nicer_error.rb +42 -71
  21. data/lib/nrser/errors/value_error.rb +53 -58
  22. data/lib/nrser/functions.rb +0 -2
  23. data/lib/nrser/functions/enumerable.rb +5 -17
  24. data/lib/nrser/functions/enumerable/associate.rb +14 -5
  25. data/lib/nrser/functions/enumerable/find_all_map.rb +1 -1
  26. data/lib/nrser/functions/enumerable/include_slice/array_include_slice.rb +1 -1
  27. data/lib/nrser/functions/hash/bury.rb +2 -12
  28. data/lib/nrser/functions/merge_by.rb +2 -2
  29. data/lib/nrser/functions/module/method_objects.rb +2 -2
  30. data/lib/nrser/functions/path.rb +185 -165
  31. data/lib/nrser/functions/path/normalized.rb +84 -0
  32. data/lib/nrser/functions/string.rb +4 -4
  33. data/lib/nrser/functions/text/README.md +4 -0
  34. data/lib/nrser/functions/text/format.rb +53 -0
  35. data/lib/nrser/functions/text/indentation.rb +6 -6
  36. data/lib/nrser/functions/text/word_wrap.rb +2 -2
  37. data/lib/nrser/functions/tree/map_leaves.rb +3 -3
  38. data/lib/nrser/functions/tree/map_tree.rb +2 -2
  39. data/lib/nrser/functions/tree/transform.rb +1 -18
  40. data/lib/nrser/gem_ext/README.md +4 -0
  41. data/lib/nrser/labs/README.md +8 -0
  42. data/lib/nrser/labs/config.rb +163 -0
  43. data/lib/nrser/labs/i8.rb +49 -159
  44. data/lib/nrser/labs/i8/struct.rb +167 -0
  45. data/lib/nrser/labs/i8/struct/hash.rb +140 -0
  46. data/lib/nrser/labs/i8/struct/vector.rb +149 -0
  47. data/lib/nrser/labs/i8/surjection.rb +211 -0
  48. data/lib/nrser/labs/lots/consumer.rb +19 -0
  49. data/lib/nrser/labs/lots/parser.rb +21 -1
  50. data/lib/nrser/labs/stash.rb +4 -4
  51. data/lib/nrser/log.rb +25 -21
  52. data/lib/nrser/log/appender/sync.rb +15 -11
  53. data/lib/nrser/log/formatters/color.rb +0 -3
  54. data/lib/nrser/log/formatters/mixin.rb +4 -4
  55. data/lib/nrser/log/logger.rb +54 -6
  56. data/lib/nrser/log/mixin.rb +2 -1
  57. data/lib/nrser/log/plugin.rb +6 -6
  58. data/lib/nrser/log/types.rb +46 -29
  59. data/lib/nrser/mean_streak.rb +0 -8
  60. data/lib/nrser/mean_streak/document.rb +1 -4
  61. data/lib/nrser/message.rb +3 -3
  62. data/lib/nrser/meta/README.md +4 -0
  63. data/lib/nrser/meta/lazy_attr.rb +2 -2
  64. data/lib/nrser/meta/source/location.rb +1 -1
  65. data/lib/nrser/props.rb +34 -3
  66. data/lib/nrser/props/class_methods.rb +2 -1
  67. data/lib/nrser/props/instance_methods.rb +9 -9
  68. data/lib/nrser/props/metadata.rb +4 -12
  69. data/lib/nrser/props/mutable/stash.rb +5 -2
  70. data/lib/nrser/props/prop.rb +10 -19
  71. data/lib/nrser/rspex.rb +1 -20
  72. data/lib/nrser/rspex/example_group/describe_attribute.rb +3 -0
  73. data/lib/nrser/rspex/example_group/describe_called_with.rb +9 -4
  74. data/lib/nrser/rspex/example_group/describe_case.rb +1 -0
  75. data/lib/nrser/rspex/example_group/describe_class.rb +2 -0
  76. data/lib/nrser/rspex/example_group/describe_group.rb +1 -1
  77. data/lib/nrser/rspex/example_group/describe_instance.rb +3 -1
  78. data/lib/nrser/rspex/example_group/describe_message.rb +1 -1
  79. data/lib/nrser/rspex/example_group/describe_method.rb +64 -30
  80. data/lib/nrser/rspex/example_group/describe_response_to.rb +1 -1
  81. data/lib/nrser/rspex/example_group/describe_section.rb +4 -1
  82. data/lib/nrser/rspex/example_group/describe_sent_to.rb +1 -1
  83. data/lib/nrser/rspex/example_group/describe_setup.rb +1 -0
  84. data/lib/nrser/rspex/example_group/describe_source_file.rb +1 -1
  85. data/lib/nrser/rspex/example_group/describe_spec_file.rb +4 -2
  86. data/lib/nrser/rspex/example_group/describe_when.rb +2 -1
  87. data/lib/nrser/rspex/example_group/describe_x.rb +5 -5
  88. data/lib/nrser/rspex/format.rb +0 -15
  89. data/lib/nrser/sugar/method_missing_forwarder.rb +3 -3
  90. data/lib/nrser/sys/env/path.rb +2 -28
  91. data/lib/nrser/types.rb +63 -12
  92. data/lib/nrser/types/README.md +76 -0
  93. data/lib/nrser/types/arrays.rb +192 -137
  94. data/lib/nrser/types/attributes.rb +269 -0
  95. data/lib/nrser/types/booleans.rb +134 -83
  96. data/lib/nrser/types/bounded.rb +110 -47
  97. data/lib/nrser/types/collections.rb +119 -0
  98. data/lib/nrser/types/combinators.rb +283 -196
  99. data/lib/nrser/types/doc/display_table.md +66 -0
  100. data/lib/nrser/types/eqiuvalent.rb +91 -0
  101. data/lib/nrser/types/errors/check_error.rb +5 -11
  102. data/lib/nrser/types/errors/from_string_error.rb +3 -3
  103. data/lib/nrser/types/factory.rb +287 -20
  104. data/lib/nrser/types/hashes.rb +227 -179
  105. data/lib/nrser/types/in.rb +73 -36
  106. data/lib/nrser/types/is.rb +67 -60
  107. data/lib/nrser/types/is_a.rb +141 -84
  108. data/lib/nrser/types/labels.rb +45 -16
  109. data/lib/nrser/types/maybe.rb +6 -3
  110. data/lib/nrser/types/nil.rb +64 -27
  111. data/lib/nrser/types/not.rb +92 -34
  112. data/lib/nrser/types/numbers.rb +224 -169
  113. data/lib/nrser/types/pairs.rb +113 -89
  114. data/lib/nrser/types/paths.rb +250 -137
  115. data/lib/nrser/types/responds.rb +167 -89
  116. data/lib/nrser/types/selector.rb +234 -0
  117. data/lib/nrser/types/shape.rb +136 -65
  118. data/lib/nrser/types/strings.rb +189 -63
  119. data/lib/nrser/types/symbols.rb +83 -33
  120. data/lib/nrser/types/top.rb +89 -0
  121. data/lib/nrser/types/tuples.rb +134 -98
  122. data/lib/nrser/types/type.rb +617 -505
  123. data/lib/nrser/types/when.rb +123 -98
  124. data/lib/nrser/types/where.rb +182 -91
  125. data/lib/nrser/version.rb +1 -1
  126. data/spec/lib/nrser/core_ext/pathname/subpath_spec.rb +22 -0
  127. data/spec/lib/nrser/errors/attr_error_spec.rb +68 -0
  128. data/spec/lib/nrser/errors/count_error_spec.rb +69 -0
  129. data/spec/lib/nrser/functions/path/normalize_path_spec.rb +35 -0
  130. data/spec/lib/nrser/functions/tree/map_tree_spec.rb +74 -96
  131. data/spec/lib/nrser/functions/tree/transform_spec.rb +11 -11
  132. data/spec/lib/nrser/labs/config_spec.rb +22 -0
  133. data/spec/lib/nrser/labs/i8/struct_spec.rb +39 -0
  134. data/spec/lib/nrser/types/display_spec.rb +50 -0
  135. data/spec/lib/nrser/types/paths_spec.rb +16 -10
  136. data/spec/lib/nrser/types/selector_spec.rb +125 -0
  137. data/spec/spec_helper.rb +4 -5
  138. metadata +105 -22
  139. data/lib/nrser/types/any.rb +0 -41
  140. data/lib/nrser/types/attrs.rb +0 -213
  141. data/lib/nrser/types/trees.rb +0 -42
@@ -10,115 +10,140 @@
10
10
  require_relative './type'
11
11
 
12
12
 
13
+ # Namespace
14
+ # ========================================================================
15
+
16
+ module NRSER
17
+ module Types
18
+
19
+
13
20
  # Definitions
14
21
  # =======================================================================
15
22
 
16
- module NRSER::Types
23
+ # Wraps an object as a type, using Ruby's "case equality" `===` to test
24
+ # membership (like a `when` clause in a `case` expression).
25
+ #
26
+ # Deals with some data loading too.
27
+ #
28
+ # @note
29
+ # This was kinda hacked in when my idiot-ass figured out that all this
30
+ # types BS could fit in real well with Ruby's `===`, allowing types to
31
+ # be used in `when` clauses.
32
+ #
33
+ # Previously, {.make} used to see if something was a module,
34
+ # and turn those into `is_a` types, and turn everything else into
35
+ # `is`, but this kind of sucked for a bunch of reasons I don't totally
36
+ # remember.
37
+ #
38
+ # Now, if a value is not a special case (like `nil`) or already a type,
39
+ # {.make} turns it into a {When}.
40
+ #
41
+ # {When} instances are totally Ruby-centric, and are thus mostly to
42
+ # support in-runtime testing - you wouldn't want a {When} type to
43
+ # be part of an API schema or something - but they're really nice for
44
+ # the internal stuff.
45
+ #
46
+ class When < Type
47
+
48
+ # The wrapped {Object} whose `#===` will be used to test membership.
49
+ #
50
+ # @return [Object]
51
+ #
52
+ attr_reader :object
53
+
54
+
55
+ # Constructor
56
+ # ======================================================================
57
+
58
+ # Instantiate a new `::When`.
59
+ def initialize object, **options
60
+ super **options
61
+ @object = object
62
+ end # #initialize
63
+
64
+
65
+ # Instance Methods
66
+ # ======================================================================
67
+
68
+ def test? value
69
+ @object === value
70
+ end
71
+
72
+
73
+ def explain
74
+ @object.inspect
75
+ end
76
+
77
+
78
+ def has_from_s?
79
+ @from_s || object.respond_to?( :from_s )
80
+ end
81
+
17
82
 
18
- # Wraps an object as a type, using Ruby's "case equality" `===` to test
19
- # membership (like a `when` clause in a `case` expression).
83
+ def custom_from_s string
84
+ object.from_s string
85
+ end
86
+
87
+
88
+ # If {#object} responds to `#from_data`, call that and check results.
20
89
  #
21
- # Deals with some data loading too.
90
+ # Otherwise, forward up to {::Type#from_data}.
22
91
  #
23
- # @note
24
- # This was kinda hacked in when my idiot-ass figured out that all this
25
- # types BS could fit in real well with Ruby's `===`, allowing types to
26
- # be used in `when` clauses.
27
- #
28
- # Previously, {NRSER::Types.make} used to see if something was a module,
29
- # and turn those into `is_a` types, and turn everything else into
30
- # `is`, but this kind of sucked for a bunch of reasons I don't totally
31
- # remember.
32
- #
33
- # Now, if a value is not a special case (like `nil`) or already a type,
34
- # {NRSER::Types.make} turns it into a {When}.
35
- #
36
- # {When} instances are totally Ruby-centric, and are thus mostly to
37
- # support in-runtime testing - you wouldn't want a {When} type to
38
- # be part of an API schema or something - but they're really nice for
39
- # the internal stuff.
92
+ # @param [Object] data
93
+ # Data to create the value from that will satisfy the type.
40
94
  #
41
- class When < Type
42
-
43
- # The wrapped {Object} whose `#===` will be used to test membership.
44
- #
45
- # @return [Object]
46
- #
47
- attr_reader :object
48
-
49
-
50
- # Constructor
51
- # ======================================================================
52
-
53
- # Instantiate a new `NRSER::Types::When`.
54
- def initialize object, **options
55
- super **options
56
- @object = object
57
- end # #initialize
58
-
59
-
60
- # Instance Methods
61
- # ======================================================================
62
-
63
- def test? value
64
- @object === value
65
- end
66
-
67
-
68
- def explain
69
- @object.inspect
70
- end
71
-
72
-
73
- def has_from_s?
74
- @from_s || object.respond_to?( :from_s )
75
- end
76
-
77
-
78
- def custom_from_s string
79
- object.from_s string
80
- end
81
-
82
-
83
- # If {#object} responds to `#from_data`, call that and check results.
84
- #
85
- # Otherwise, forward up to {NRSER::Types::Type#from_data}.
86
- #
87
- # @param [Object] data
88
- # Data to create the value from that will satisfy the type.
89
- #
90
- # @return [Object]
91
- # Instance of {#object}.
92
- #
93
- def from_data data
94
- if @from_data.nil?
95
- if @object.respond_to? :from_data
96
- check @object.from_data( data )
97
- else
98
- super data
99
- end
95
+ # @return [Object]
96
+ # Instance of {#object}.
97
+ #
98
+ def from_data data
99
+ if @from_data.nil?
100
+ if @object.respond_to? :from_data
101
+ check @object.from_data( data )
100
102
  else
101
- @from_data.call data
103
+ super data
102
104
  end
105
+ else
106
+ @from_data.call data
103
107
  end
104
-
105
-
106
- def has_from_data?
107
- @from_data || @object.respond_to?( :from_data )
108
- end
109
-
110
-
111
- def == other
112
- equal?( other ) ||
113
- ( self.class == other.class &&
114
- self.object == other.object )
115
- end
116
-
117
- end # class When
108
+ end
118
109
 
119
110
 
120
- def_factory :when do |value, **options|
121
- When.new value, **options
111
+ def has_from_data?
112
+ @from_data || @object.respond_to?( :from_data )
122
113
  end
123
114
 
124
- end # module NRSER::Types
115
+
116
+ def == other
117
+ equal?( other ) ||
118
+ ( self.class == other.class &&
119
+ self.object == other.object )
120
+ end
121
+
122
+ end # class When
123
+
124
+
125
+ #@!method self.When value, **options
126
+ # Get a type parameterizing a `value` whose members are all objects `obj`
127
+ # such that `value === obj` ("case equality").
128
+ #
129
+ # @param [Object] value
130
+ # Any object.
131
+ #
132
+ # @param [Hash] options
133
+ # Passed to {Type#initialize}.
134
+ #
135
+ # @return [When]
136
+ #
137
+ def_type :When,
138
+ parameterize: :value,
139
+ default_name: false,
140
+ &->( value, **options ) do
141
+ When.new value, **options
142
+ end # .When
143
+
144
+
145
+ # /Namespace
146
+ # ========================================================================
147
+
148
+ end # module Types
149
+ end # module NRSER
@@ -1,107 +1,198 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'nrser/core_ext/method'
5
+
4
6
  require_relative './type'
5
7
 
6
- module NRSER::Types
8
+
9
+ # Namespace
10
+ # ========================================================================
11
+
12
+ module NRSER
13
+ module Types
14
+
15
+
16
+ # Definitions
17
+ # ========================================================================
18
+
19
+ # {Where} instances are predicate functions¹ as a type.
20
+ #
21
+ # They have a {#predicate} block, and {#test?} calls it with values and
22
+ # returns the boolean of the result (double-bangs it `!!`).
23
+ #
24
+ # Super simple, right? And easy! Why don't we just use these things all over
25
+ # the place?
26
+ #
27
+ # If you're been around the programing block a few times, you probably saw
28
+ # this coming a mile away: you should avoid using them.
29
+ #
30
+ # Yeah, sorry. Here's the reasons:
31
+ #
32
+ # 1. They're **opaque** - it's hard to see inside a {Proc}... even if you
33
+ # got the source code (which seems like it requires gems and involves
34
+ # some amount of hackery), that wouldn't really give you the whole
35
+ # picture because you need to look at the binding as well... Ruby
36
+ # procs capture their entire environment.
37
+ #
38
+ # Essentially, they suck to easily and/or comprehensively communicate
39
+ # what they hell they do.
40
+ #
41
+ # 2. Like {When}, they're totally Ruby-centric... we can't really serialize
42
+ # them and pass them off anywhere, so they're shitty for APIs and
43
+ # property types and stuff that you may want or need to expose outside
44
+ # the runtime.
45
+ #
46
+ # In this sense they're ok as implementations of types like {.file_path}
47
+ # that represent an *idea* to be communicated to the outside world,
48
+ # where each system that handles that idea will need to have it's own
49
+ # implementation of it.
50
+ #
51
+ # Lit addresses a lot of this with serializable functions, but that's
52
+ # nowhere near ready to rock, and support for it would probably be
53
+ # added along side {Where}, not in place of it (since {Where} is
54
+ # probably still going to be used and useful).
55
+ #
56
+ # So please be aware of those, and be reasonable about your {Where}s.
57
+ #
58
+ # > ¹ I say *functions*, because they really *should* be functions (same
59
+ # > input always gets same output, pure, etc.).
60
+ # >
61
+ # > Yeah, there's not much stopping you from making them state-based or
62
+ # > random or whatever, but please don't do that shit unless you've really
63
+ # > thought it through. And if you still do, please write me and tell me
64
+ # > what you thought and why it's a reasonable idea and I'll update this.
65
+ #
66
+ class Where < Type
7
67
 
8
- # {Where} instances are predicate functions¹ as a type.
9
- #
10
- # They have a {#predicate} block, and {#test?} calls it with values and
11
- # returns the boolean of the result (double-bangs it `!!`).
12
- #
13
- # Super simple, right? And easy! Why don't we just use these things all over
14
- # the place?
15
- #
16
- # If you're been around the programing block a few times, you probably saw
17
- # this coming a mile away: you should avoid using them.
18
- #
19
- # Yeah, sorry. Here's the reasons:
20
- #
21
- # 1. They're **opaque** - it's hard to see inside a {Proc}... even if you
22
- # got the source code (which seems like it requires gems and involves
23
- # some amount of hackery), that wouldn't really give you the whole
24
- # picture because you need to look at the binding as well... Ruby
25
- # procs capture their entire environment.
26
- #
27
- # Essentially, they suck to easily and/or comprehensively communicate
28
- # what they hell they do.
29
- #
30
- # 2. Like {When}, they're totally Ruby-centric... we can't really serialize
31
- # them and pass them off anywhere, so they're shitty for APIs and
32
- # property types and stuff that you may want or need to expose outside
33
- # the runtime.
34
- #
35
- # In this sense they're ok as implementations of types like {.file_path}
36
- # that represent an *idea* to be communicated to the outside world,
37
- # where each system that handles that idea will need to have it's own
38
- # implementation of it.
39
- #
40
- # Lit addresses a lot of this with serializable functions, but that's
41
- # nowhere near ready to rock, and support for it would probably be
42
- # added along side {Where}, not in place of it (since {Where} is
43
- # probably still going to be used and useful).
44
- #
45
- # So please be aware of those, and be reasonable about your {Where}s.
46
- #
47
- # > ¹ I say *functions*, because they really *should* be functions (same
48
- # > input always gets same output, pure, etc.).
49
- # >
50
- # > Yeah, there's not much stopping you from making them state-based or
51
- # > random or whatever, but please don't do that shit unless you've really
52
- # > thought it through. And if you still do, please write me and tell me
53
- # > what you thought and why it's a reasonable idea and I'll update this.
54
- #
55
- class Where < NRSER::Types::Type
56
-
57
- # Predicate {Proc} used to test value for membership.
58
- #
59
- # @return [Proc<(V) => Boolean>]
60
- # Really, we double-bang (`!!`) whatever the predicate returns to
61
- # get the result in {#test?}, but you get the idea... the response will
62
- # be evaluated on its truthiness.
63
- #
64
- attr_reader :predicate
65
-
66
-
67
- # Make a new {Where}.
68
- #
69
- # @param [Proc<(V) => Boolean>] &predicate
70
- # See {#predicate}.
71
- #
72
- # @param **options (see NRSER::Types::Type#initialize)
73
- #
74
- def initialize **options, &predicate
75
- super **options
68
+ # Predicate {Proc} used to test value for membership.
69
+ #
70
+ # @return [Proc<(V) => Boolean>]
71
+ # Really, we double-bang (`!!`) whatever the predicate returns to
72
+ # get the result in {#test?}, but you get the idea... the response will
73
+ # be evaluated on its truthiness.
74
+ #
75
+ attr_reader :predicate
76
+
77
+
78
+ # Make a new {Where}.
79
+ #
80
+ # @note
81
+ # Documentation and examples are indented to illustrate behavior and
82
+ # aid in development. Please use the factory method {Types.where} to
83
+ # create instances - they allow us to easily improve and optimize
84
+ #
85
+ #
86
+ # @overload initialize method, **options
87
+ #
88
+ # This is the preferred form, where a bound method provide the membership
89
+ # predicate.
90
+ #
91
+ # Class or module methods make the most sense, though this is not enforced.
92
+ #
93
+ # @example Create a {Type} that tests if a path is a file
94
+ # type = Where.new File.method( :file? )
95
+ #
96
+ # @param [Method<(Object)=>Boolean>] method
97
+ # Arity 1 bound method that will be used to decide membership (if it
98
+ # responds truthy then the argument is a member of the type).
99
+ #
100
+ # @param [Hash] options
101
+ # Additional options that will be passed up to {Type#initialize}.
102
+ #
103
+ #
104
+ # @overload initialize **options, &block
105
+ #
106
+ # This form should be used sparingly - please use a bound class or module
107
+ # {Method} instead of an opaque `&block` for the predicate.
108
+ #
109
+ # it exists mostly for legacy reasons, and for the
110
+ #
111
+ # @param [String] name
112
+ # In this form, a `name` is required because it is not usually possible
113
+ # to extract any descriptive information from the `&block`.
114
+ #
115
+ # @param [Hash] options
116
+ # Additional options that will be passed up to {Type#initialize}.
117
+ #
118
+ # @param [Proc<(Object)=>Boolean>] block
119
+ # Arity 1 {Proc} that will be used to decide membership (if it responds
120
+ # truthy then the argument is a member of the type).
121
+ #
122
+ #
123
+ def initialize method = nil, **options, &block
124
+ # Check up on what we got
125
+
126
+ if method && block
127
+ raise NRSER::ArgumentError.new \
128
+ "Can't supply both method", method, "(first arg)",
129
+ "and &block", block
76
130
 
77
- unless predicate.arity == 1
78
- raise NRSER::ArgumentError.new \
79
- "Predicate block must have arity 1",
80
- predicate: predicate,
81
- options: options
82
- end
131
+ elsif !method && !block
132
+ raise NRSER::ArgumentError.new \
133
+ "Must provide either a Method<(Object)=>Boolean> as the first argument",
134
+ "*or* a Proc<(Object)=>Boolean> as the block"
83
135
 
84
- @predicate = predicate
85
136
  end
137
+
138
+ @predicate = method || block
86
139
 
87
-
88
- # Test a value for membership.
89
- #
90
- # @param (see NRSER::Types::Type#test?)
91
- # @return (see NRSER::Types::Type#test?)
92
- # @raise (see NRSER::Types::Type#test?)
93
- #
94
- def test? value
95
- !!@predicate.call(value)
140
+ unless predicate.arity == 1
141
+ raise NRSER::ArgumentError.new \
142
+ "{NRSER::Types::Where} predicates must have arity 1",
143
+ predicate: predicate,
144
+ arity: predicate.arity,
145
+ options: options
96
146
  end
97
-
98
- end # class Where
147
+
148
+ unless options[:name]
149
+ if predicate.is_a?( Method )
150
+ options[:name] = predicate.full_name
151
+ else
152
+ raise NRSER::ArgumentError.new \
153
+ "`name:` keyword argument is required when creating {Where}",
154
+ "from `&block` predicates."
155
+ end
156
+ end
157
+
158
+ super **options
159
+
160
+ end
99
161
 
100
162
 
101
- # Get a type based on a predicate.
163
+ # Test a value for membership.
164
+ #
165
+ # @param (see Type#test?)
166
+ # @return (see Type#test?)
167
+ # @raise (see Type#test?)
102
168
  #
103
- def_factory :where do |**options, &predicate|
104
- Where.new **options, &predicate
169
+ def test? value
170
+ !!@predicate.call( value )
171
+ end
172
+
173
+
174
+ # A string that is supposed to give our best concise description of the type.
175
+ #
176
+ # {Where} sucks because we can't really do much here.
177
+ #
178
+ # @return [String]
179
+ #
180
+ def explain
181
+ "#{ self.class.demod_name }<#{ @name }>"
105
182
  end
106
183
 
107
- end # NRSER::Types
184
+ end # class Where ************************************************************
185
+
186
+
187
+ # Get a type based on a predicate.
188
+ #
189
+ def_type :Where, &->( *args, &block ) do
190
+ Where.new *args, &block
191
+ end
192
+
193
+
194
+ # /Namespace
195
+ # ========================================================================
196
+
197
+ end # module Types
198
+ end # module NRSER