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.
- checksums.yaml +4 -4
- data/lib/nrser/char/alpha_numeric_sub.rb +9 -19
- data/lib/nrser/char/special.rb +5 -5
- data/lib/nrser/core_ext/array.rb +36 -13
- data/lib/nrser/core_ext/enumerable.rb +1 -0
- data/lib/nrser/core_ext/enumerable/find_map.rb +1 -1
- data/lib/nrser/core_ext/hash/bury.rb +3 -0
- data/lib/nrser/core_ext/hash/extract_values_at.rb +2 -2
- data/lib/nrser/core_ext/method/full_name.rb +1 -1
- data/lib/nrser/core_ext/module/method_objects.rb +1 -1
- data/lib/nrser/core_ext/module/source_locations.rb +27 -15
- data/lib/nrser/core_ext/object/lazy_var.rb +1 -1
- data/lib/nrser/core_ext/pathname.rb +67 -12
- data/lib/nrser/core_ext/pathname/subpath.rb +86 -0
- data/lib/nrser/core_ext/string.rb +28 -1
- data/lib/nrser/core_ext/symbol.rb +11 -12
- data/lib/nrser/errors/README.md +154 -0
- data/lib/nrser/errors/attr_error.rb +146 -53
- data/lib/nrser/errors/count_error.rb +61 -12
- data/lib/nrser/errors/nicer_error.rb +42 -71
- data/lib/nrser/errors/value_error.rb +53 -58
- data/lib/nrser/functions.rb +0 -2
- data/lib/nrser/functions/enumerable.rb +5 -17
- data/lib/nrser/functions/enumerable/associate.rb +14 -5
- data/lib/nrser/functions/enumerable/find_all_map.rb +1 -1
- data/lib/nrser/functions/enumerable/include_slice/array_include_slice.rb +1 -1
- data/lib/nrser/functions/hash/bury.rb +2 -12
- data/lib/nrser/functions/merge_by.rb +2 -2
- data/lib/nrser/functions/module/method_objects.rb +2 -2
- data/lib/nrser/functions/path.rb +185 -165
- data/lib/nrser/functions/path/normalized.rb +84 -0
- data/lib/nrser/functions/string.rb +4 -4
- data/lib/nrser/functions/text/README.md +4 -0
- data/lib/nrser/functions/text/format.rb +53 -0
- data/lib/nrser/functions/text/indentation.rb +6 -6
- data/lib/nrser/functions/text/word_wrap.rb +2 -2
- data/lib/nrser/functions/tree/map_leaves.rb +3 -3
- data/lib/nrser/functions/tree/map_tree.rb +2 -2
- data/lib/nrser/functions/tree/transform.rb +1 -18
- data/lib/nrser/gem_ext/README.md +4 -0
- data/lib/nrser/labs/README.md +8 -0
- data/lib/nrser/labs/config.rb +163 -0
- data/lib/nrser/labs/i8.rb +49 -159
- data/lib/nrser/labs/i8/struct.rb +167 -0
- data/lib/nrser/labs/i8/struct/hash.rb +140 -0
- data/lib/nrser/labs/i8/struct/vector.rb +149 -0
- data/lib/nrser/labs/i8/surjection.rb +211 -0
- data/lib/nrser/labs/lots/consumer.rb +19 -0
- data/lib/nrser/labs/lots/parser.rb +21 -1
- data/lib/nrser/labs/stash.rb +4 -4
- data/lib/nrser/log.rb +25 -21
- data/lib/nrser/log/appender/sync.rb +15 -11
- data/lib/nrser/log/formatters/color.rb +0 -3
- data/lib/nrser/log/formatters/mixin.rb +4 -4
- data/lib/nrser/log/logger.rb +54 -6
- data/lib/nrser/log/mixin.rb +2 -1
- data/lib/nrser/log/plugin.rb +6 -6
- data/lib/nrser/log/types.rb +46 -29
- data/lib/nrser/mean_streak.rb +0 -8
- data/lib/nrser/mean_streak/document.rb +1 -4
- data/lib/nrser/message.rb +3 -3
- data/lib/nrser/meta/README.md +4 -0
- data/lib/nrser/meta/lazy_attr.rb +2 -2
- data/lib/nrser/meta/source/location.rb +1 -1
- data/lib/nrser/props.rb +34 -3
- data/lib/nrser/props/class_methods.rb +2 -1
- data/lib/nrser/props/instance_methods.rb +9 -9
- data/lib/nrser/props/metadata.rb +4 -12
- data/lib/nrser/props/mutable/stash.rb +5 -2
- data/lib/nrser/props/prop.rb +10 -19
- data/lib/nrser/rspex.rb +1 -20
- data/lib/nrser/rspex/example_group/describe_attribute.rb +3 -0
- data/lib/nrser/rspex/example_group/describe_called_with.rb +9 -4
- data/lib/nrser/rspex/example_group/describe_case.rb +1 -0
- data/lib/nrser/rspex/example_group/describe_class.rb +2 -0
- data/lib/nrser/rspex/example_group/describe_group.rb +1 -1
- data/lib/nrser/rspex/example_group/describe_instance.rb +3 -1
- data/lib/nrser/rspex/example_group/describe_message.rb +1 -1
- data/lib/nrser/rspex/example_group/describe_method.rb +64 -30
- data/lib/nrser/rspex/example_group/describe_response_to.rb +1 -1
- data/lib/nrser/rspex/example_group/describe_section.rb +4 -1
- data/lib/nrser/rspex/example_group/describe_sent_to.rb +1 -1
- data/lib/nrser/rspex/example_group/describe_setup.rb +1 -0
- data/lib/nrser/rspex/example_group/describe_source_file.rb +1 -1
- data/lib/nrser/rspex/example_group/describe_spec_file.rb +4 -2
- data/lib/nrser/rspex/example_group/describe_when.rb +2 -1
- data/lib/nrser/rspex/example_group/describe_x.rb +5 -5
- data/lib/nrser/rspex/format.rb +0 -15
- data/lib/nrser/sugar/method_missing_forwarder.rb +3 -3
- data/lib/nrser/sys/env/path.rb +2 -28
- data/lib/nrser/types.rb +63 -12
- data/lib/nrser/types/README.md +76 -0
- data/lib/nrser/types/arrays.rb +192 -137
- data/lib/nrser/types/attributes.rb +269 -0
- data/lib/nrser/types/booleans.rb +134 -83
- data/lib/nrser/types/bounded.rb +110 -47
- data/lib/nrser/types/collections.rb +119 -0
- data/lib/nrser/types/combinators.rb +283 -196
- data/lib/nrser/types/doc/display_table.md +66 -0
- data/lib/nrser/types/eqiuvalent.rb +91 -0
- data/lib/nrser/types/errors/check_error.rb +5 -11
- data/lib/nrser/types/errors/from_string_error.rb +3 -3
- data/lib/nrser/types/factory.rb +287 -20
- data/lib/nrser/types/hashes.rb +227 -179
- data/lib/nrser/types/in.rb +73 -36
- data/lib/nrser/types/is.rb +67 -60
- data/lib/nrser/types/is_a.rb +141 -84
- data/lib/nrser/types/labels.rb +45 -16
- data/lib/nrser/types/maybe.rb +6 -3
- data/lib/nrser/types/nil.rb +64 -27
- data/lib/nrser/types/not.rb +92 -34
- data/lib/nrser/types/numbers.rb +224 -169
- data/lib/nrser/types/pairs.rb +113 -89
- data/lib/nrser/types/paths.rb +250 -137
- data/lib/nrser/types/responds.rb +167 -89
- data/lib/nrser/types/selector.rb +234 -0
- data/lib/nrser/types/shape.rb +136 -65
- data/lib/nrser/types/strings.rb +189 -63
- data/lib/nrser/types/symbols.rb +83 -33
- data/lib/nrser/types/top.rb +89 -0
- data/lib/nrser/types/tuples.rb +134 -98
- data/lib/nrser/types/type.rb +617 -505
- data/lib/nrser/types/when.rb +123 -98
- data/lib/nrser/types/where.rb +182 -91
- data/lib/nrser/version.rb +1 -1
- data/spec/lib/nrser/core_ext/pathname/subpath_spec.rb +22 -0
- data/spec/lib/nrser/errors/attr_error_spec.rb +68 -0
- data/spec/lib/nrser/errors/count_error_spec.rb +69 -0
- data/spec/lib/nrser/functions/path/normalize_path_spec.rb +35 -0
- data/spec/lib/nrser/functions/tree/map_tree_spec.rb +74 -96
- data/spec/lib/nrser/functions/tree/transform_spec.rb +11 -11
- data/spec/lib/nrser/labs/config_spec.rb +22 -0
- data/spec/lib/nrser/labs/i8/struct_spec.rb +39 -0
- data/spec/lib/nrser/types/display_spec.rb +50 -0
- data/spec/lib/nrser/types/paths_spec.rb +16 -10
- data/spec/lib/nrser/types/selector_spec.rb +125 -0
- data/spec/spec_helper.rb +4 -5
- metadata +105 -22
- data/lib/nrser/types/any.rb +0 -41
- data/lib/nrser/types/attrs.rb +0 -213
- data/lib/nrser/types/trees.rb +0 -42
data/lib/nrser/types/when.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
19
|
-
|
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
|
-
#
|
90
|
+
# Otherwise, forward up to {::Type#from_data}.
|
22
91
|
#
|
23
|
-
# @
|
24
|
-
#
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
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
|
-
|
121
|
-
|
111
|
+
def has_from_data?
|
112
|
+
@from_data || @object.respond_to?( :from_data )
|
122
113
|
end
|
123
114
|
|
124
|
-
|
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
|
data/lib/nrser/types/where.rb
CHANGED
@@ -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
|
-
|
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
|
-
# {
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
|
104
|
-
|
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 #
|
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
|