nrser 0.3.9 → 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
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