fear 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +27 -0
  3. data/.github/workflows/rubocop.yml +2 -2
  4. data/.github/workflows/spec.yml +1 -1
  5. data/CHANGELOG.md +13 -0
  6. data/Gemfile.lock +53 -56
  7. data/README.md +54 -186
  8. data/Rakefile +0 -21
  9. data/examples/pattern_extracting.rb +4 -4
  10. data/fear.gemspec +2 -4
  11. data/lib/fear/either.rb +8 -4
  12. data/lib/fear/either_api.rb +2 -0
  13. data/lib/fear/either_pattern_match.rb +7 -8
  14. data/lib/fear/failure.rb +0 -9
  15. data/lib/fear/failure_pattern_match.rb +2 -0
  16. data/lib/fear/for_api.rb +2 -0
  17. data/lib/fear/future.rb +12 -20
  18. data/lib/fear/future_api.rb +13 -2
  19. data/lib/fear/left.rb +0 -9
  20. data/lib/fear/none.rb +7 -9
  21. data/lib/fear/option.rb +5 -1
  22. data/lib/fear/option_api.rb +2 -0
  23. data/lib/fear/option_pattern_match.rb +6 -4
  24. data/lib/fear/partial_function/empty.rb +2 -0
  25. data/lib/fear/partial_function/guard.rb +4 -4
  26. data/lib/fear/partial_function/or_else.rb +2 -0
  27. data/lib/fear/partial_function.rb +9 -8
  28. data/lib/fear/pattern_match.rb +0 -10
  29. data/lib/fear/pattern_matching_api.rb +3 -28
  30. data/lib/fear/promise.rb +3 -9
  31. data/lib/fear/right.rb +0 -10
  32. data/lib/fear/right_biased.rb +1 -1
  33. data/lib/fear/right_pattern_match.rb +2 -0
  34. data/lib/fear/some.rb +7 -10
  35. data/lib/fear/struct.rb +3 -14
  36. data/lib/fear/success.rb +0 -9
  37. data/lib/fear/success_pattern_match.rb +2 -0
  38. data/lib/fear/try.rb +6 -2
  39. data/lib/fear/try_api.rb +2 -0
  40. data/lib/fear/try_pattern_match.rb +7 -8
  41. data/lib/fear/utils.rb +0 -3
  42. data/lib/fear/version.rb +1 -1
  43. data/lib/fear.rb +8 -42
  44. data/spec/fear/awaitable_spec.rb +2 -0
  45. data/spec/fear/either_spec.rb +26 -0
  46. data/spec/fear/failure_spec.rb +8 -23
  47. data/spec/fear/for/mixin_spec.rb +15 -0
  48. data/spec/fear/future_spec.rb +17 -2
  49. data/spec/fear/guard_spec.rb +110 -0
  50. data/spec/fear/left_spec.rb +7 -22
  51. data/spec/fear/none_spec.rb +11 -17
  52. data/spec/fear/option_spec.rb +15 -1
  53. data/spec/fear/partial_function/any_spec.rb +25 -0
  54. data/spec/fear/partial_function_spec.rb +2 -24
  55. data/spec/fear/pattern_match_spec.rb +0 -34
  56. data/spec/fear/promise_spec.rb +4 -6
  57. data/spec/fear/right_spec.rb +0 -22
  58. data/spec/fear/some_spec.rb +10 -22
  59. data/spec/fear/success_spec.rb +0 -22
  60. data/spec/fear/try/mixin_spec.rb +14 -0
  61. data/spec/fear/try_api_spec.rb +23 -0
  62. data/spec/struct_spec.rb +1 -33
  63. metadata +18 -80
  64. data/examples/pattern_extracting_ruby2.7.rb +0 -15
  65. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -10
  66. data/lib/fear/extractor/any_matcher.rb +0 -17
  67. data/lib/fear/extractor/array_head_matcher.rb +0 -36
  68. data/lib/fear/extractor/array_matcher.rb +0 -40
  69. data/lib/fear/extractor/array_splat_matcher.rb +0 -16
  70. data/lib/fear/extractor/empty_list_matcher.rb +0 -20
  71. data/lib/fear/extractor/extractor_matcher.rb +0 -44
  72. data/lib/fear/extractor/grammar.rb +0 -203
  73. data/lib/fear/extractor/grammar.treetop +0 -129
  74. data/lib/fear/extractor/identifier_matcher.rb +0 -18
  75. data/lib/fear/extractor/matcher/and.rb +0 -38
  76. data/lib/fear/extractor/matcher.rb +0 -53
  77. data/lib/fear/extractor/named_array_splat_matcher.rb +0 -17
  78. data/lib/fear/extractor/pattern.rb +0 -58
  79. data/lib/fear/extractor/typed_identifier_matcher.rb +0 -26
  80. data/lib/fear/extractor/value_matcher.rb +0 -19
  81. data/lib/fear/extractor.rb +0 -112
  82. data/lib/fear/extractor_api.rb +0 -35
  83. data/spec/fear/extractor/array_matcher_spec.rb +0 -230
  84. data/spec/fear/extractor/extractor_matcher_spec.rb +0 -153
  85. data/spec/fear/extractor/grammar_array_spec.rb +0 -25
  86. data/spec/fear/extractor/identified_matcher_spec.rb +0 -49
  87. data/spec/fear/extractor/identifier_matcher_spec.rb +0 -68
  88. data/spec/fear/extractor/pattern_spec.rb +0 -34
  89. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -64
  90. data/spec/fear/extractor/value_matcher_number_spec.rb +0 -79
  91. data/spec/fear/extractor/value_matcher_string_spec.rb +0 -88
  92. data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -71
  93. data/spec/fear/extractor_api_spec.rb +0 -115
  94. data/spec/fear/extractor_spec.rb +0 -61
@@ -1,203 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # This module contains AST nodes for GrammarParser
6
- # generated by +treetop+. The sole purpose of them all is to
7
- # generate matchers
8
- module Grammar
9
- class Node < Treetop::Runtime::SyntaxNode
10
- end
11
-
12
- class EmptyArray < Node
13
- def to_matcher
14
- EmptyListMatcher.new(node: self)
15
- end
16
- end
17
-
18
- class ArrayLiteral < Node
19
- def to_matcher
20
- elements[1].to_matcher
21
- end
22
- end
23
-
24
- class NonEmptyArray < Node
25
- def to_matcher
26
- head, tail = elements
27
- ArrayMatcher.new(head: head.to_matcher, tail: tail.to_matcher, node: self)
28
- end
29
- end
30
-
31
- class ArrayTail < Node
32
- def to_matcher
33
- elements[1].to_matcher
34
- end
35
- end
36
-
37
- class ArrayHead < Node
38
- def to_matcher
39
- ArrayHeadMatcher.new(matcher: elements[1].to_matcher, node: elements[1])
40
- end
41
- end
42
-
43
- class ArraySplat < Node
44
- def to_matcher
45
- elements[1].to_matcher
46
- end
47
- end
48
-
49
- class AnonymousArraySplat < Node
50
- def to_matcher
51
- AnonymousArraySplatMatcher.new(node: self)
52
- end
53
- end
54
-
55
- class FloatLiteral < Node
56
- def to_matcher
57
- ValueMatcher.new(value: value, node: self)
58
- end
59
-
60
- def value
61
- Float(text_value)
62
- end
63
- end
64
-
65
- class IntegerLiteral < Node
66
- def to_matcher
67
- ValueMatcher.new(value: value, node: self)
68
- end
69
-
70
- def value
71
- Integer(text_value, 10)
72
- end
73
- end
74
-
75
- class StringLiteral < Node
76
- def to_matcher
77
- ValueMatcher.new(value: value, node: self)
78
- end
79
-
80
- def value
81
- elements[1].text_value
82
- end
83
- end
84
-
85
- require "yaml"
86
-
87
- class DoubleQuotedStringLiteral < StringLiteral
88
- def to_matcher
89
- ValueMatcher.new(value: value, node: self)
90
- end
91
-
92
- def value
93
- YAML.safe_load(%(---\n"#{super}"\n))
94
- end
95
- end
96
-
97
- class SymbolLiteral < Node
98
- def to_matcher
99
- ValueMatcher.new(value: value, node: self)
100
- end
101
-
102
- def value
103
- elements[1].value.to_sym
104
- end
105
- end
106
-
107
- class TrueLiteral < Node
108
- def to_matcher
109
- ValueMatcher.new(value: true, node: self)
110
- end
111
- end
112
-
113
- class FalseLiteral < Node
114
- def to_matcher
115
- ValueMatcher.new(value: false, node: self)
116
- end
117
- end
118
-
119
- class NilLiteral < Node
120
- def to_matcher
121
- ValueMatcher.new(value: nil, node: self)
122
- end
123
- end
124
-
125
- class AnyIdentifier < Node
126
- def to_matcher
127
- AnyMatcher.new(node: self)
128
- end
129
- end
130
-
131
- class Identifier < Node
132
- def to_matcher
133
- IdentifierMatcher.new(name: value, node: self)
134
- end
135
-
136
- def value
137
- text_value.to_sym
138
- end
139
- end
140
-
141
- class NamedArraySplat < Node
142
- def to_matcher
143
- NamedArraySplatMatcher.new(name: name, node: self)
144
- end
145
-
146
- def name
147
- text_value[1..-1].to_sym
148
- end
149
- end
150
-
151
- class TypeLiteral < Node
152
- def to_matcher
153
- ValueMatcher.new(value: value, node: self)
154
- end
155
-
156
- def value
157
- Object.const_get(text_value)
158
- end
159
- end
160
-
161
- class TypedIdentifier < Node
162
- def to_matcher
163
- identifier, type = elements.values_at(0, 2)
164
- type.to_matcher.and(identifier.to_matcher)
165
- end
166
- end
167
-
168
- class IdentifiedMatcher < Node
169
- def to_matcher
170
- identifier, matcher = elements.values_at(0, -1)
171
- identifier.to_matcher.and(matcher.to_matcher)
172
- end
173
- end
174
-
175
- class ExtractorLiteral < Node
176
- def to_matcher
177
- ExtractorMatcher.new(
178
- name: extractor_name,
179
- arguments_matcher: extractor_arguments,
180
- node: self,
181
- )
182
- end
183
-
184
- private def extractor_name
185
- name = elements[0].text_value
186
- if Object.const_defined?(name)
187
- Object.const_get(name)
188
- else
189
- name
190
- end
191
- end
192
-
193
- private def extractor_arguments
194
- if elements[2].empty?
195
- EmptyListMatcher.new(node: self)
196
- else
197
- elements[2].to_matcher
198
- end
199
- end
200
- end
201
- end
202
- end
203
- end
@@ -1,129 +0,0 @@
1
- # PEG grammar for pattern matching and extracting
2
-
3
- module Fear::Extractor
4
- grammar Grammar
5
- rule matcher
6
- identified_matcher / anonymous_matcher
7
- end
8
-
9
- rule identified_matcher
10
- identifier space '@' space anonymous_matcher <IdentifiedMatcher>
11
- end
12
-
13
- rule anonymous_matcher
14
- array / literal / identifier / extractor / type
15
- end
16
-
17
- rule array
18
- '[' (non_empty_array / array_splat / empty_array) ']' <ArrayLiteral>
19
- end
20
-
21
- rule empty_array
22
- '' <EmptyArray>
23
- end
24
-
25
- rule non_empty_array
26
- array_head (array_tail / empty_array) <NonEmptyArray>
27
- end
28
-
29
- rule array_tail
30
- ',' (non_empty_array / array_splat) <ArrayTail>
31
- end
32
-
33
- rule array_splat
34
- space? (named_array_splat / anonymous_array_splat) space? <ArraySplat>
35
- end
36
-
37
- rule array_splat_identifier
38
- space? anonymous_array_splat space? <ArraySplat>
39
- end
40
-
41
- rule anonymous_array_splat
42
- '*' '_'? <AnonymousArraySplat>
43
- end
44
-
45
- rule named_array_splat
46
- '*' [a-z] [a-z0-9_]* <NamedArraySplat>
47
- end
48
-
49
- rule array_head
50
- space? anonymous_matcher space? <ArrayHead>
51
- end
52
-
53
- rule space
54
- [\s]+
55
- end
56
-
57
- rule any
58
- '_' <AnyIdentifier>
59
- end
60
-
61
- rule variable_identifier
62
- [a-z_] [a-z0-9_]* <Identifier>
63
- end
64
-
65
- rule identifier
66
- typed_identifier / any / variable_identifier
67
- end
68
-
69
- rule typed_identifier
70
- (any / variable_identifier) ' : ' type <TypedIdentifier>
71
- end
72
-
73
- rule literal
74
- nil / true / false / number / string / symbol
75
- end
76
-
77
- rule number
78
- float / integer
79
- end
80
-
81
- rule integer
82
- ('+' / '-')? [0-9]+ <IntegerLiteral>
83
- end
84
-
85
- rule float
86
- ('+' / '-')? [0-9]+ '.' [0-9]+ <FloatLiteral>
87
- end
88
-
89
- rule symbol
90
- ':' (string / any / variable_identifier) <SymbolLiteral>
91
- end
92
-
93
- rule string
94
- double_quoted_string / single_quoted_string
95
- end
96
-
97
- rule double_quoted_string
98
- '"' ([^"\\] / '\\' . )* '"' <DoubleQuotedStringLiteral>
99
- end
100
-
101
- rule single_quoted_string
102
- "'" ([^'\\] / '\\' . )* "'" <StringLiteral>
103
- end
104
-
105
- rule true
106
- 'true' <TrueLiteral>
107
- end
108
-
109
- rule false
110
- 'false' <FalseLiteral>
111
- end
112
-
113
- rule nil
114
- 'nil' <NilLiteral>
115
- end
116
-
117
- rule extractor
118
- type '(' non_empty_array? ')' <ExtractorLiteral>
119
- end
120
-
121
- rule type
122
- constant ('::' constant)* <TypeLiteral>
123
- end
124
-
125
- rule constant
126
- [A-Z] [a-zA-Z0-9_]*
127
- end
128
- end
129
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- class IdentifierMatcher < Matcher
6
- # @!attribute name
7
- # @return [Types::Strict::Symbol]
8
-
9
- def defined_at?(_)
10
- true
11
- end
12
-
13
- def bindings(other)
14
- { name => other }
15
- end
16
- end
17
- end
18
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "ostruct"
4
-
5
- module Fear
6
- module Extractor
7
- class Matcher < OpenStruct
8
- # Combine two matchers, so both should pass
9
- class And < Matcher
10
- def initialize(matcher1, matcher2)
11
- @matcher1 = matcher1
12
- @matcher2 = matcher2
13
- end
14
- attr_reader :matcher1, :matcher2
15
-
16
- def defined_at?(arg)
17
- matcher1.defined_at?(arg) && matcher2.defined_at?(arg)
18
- end
19
-
20
- def bindings(arg)
21
- matcher1.bindings(arg).merge(matcher2.bindings(arg))
22
- end
23
-
24
- def failure_reason(arg)
25
- if matcher1.defined_at?(arg)
26
- if matcher2.defined_at?(arg)
27
- Fear.none
28
- else
29
- matcher2.failure_reason(arg)
30
- end
31
- else
32
- matcher1.failure_reason(arg)
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "ostruct"
4
-
5
- module Fear
6
- module Extractor
7
- # @abstract abstract matcher to inherit from.
8
- class Matcher < OpenStruct
9
- autoload :And, "fear/extractor/matcher/and"
10
-
11
- # @param node [Fear::Extractor::Grammar::Node]
12
- def initialize(node:, **attributes)
13
- @input = node.input
14
- @input_position = node.interval.first
15
- super(attributes)
16
- end
17
- attr_reader :input_position, :input
18
- private :input
19
- private :input_position
20
-
21
- def call(arg)
22
- call_or_else(arg, &PartialFunction::EMPTY)
23
- end
24
-
25
- def and(other)
26
- And.new(self, other)
27
- end
28
-
29
- # @param arg [any]
30
- # @yield [arg] if function not defined
31
- def call_or_else(arg)
32
- if defined_at?(arg)
33
- bindings(arg)
34
- else
35
- yield arg
36
- end
37
- end
38
-
39
- # Shows why matcher has failed. Use it for debugging.
40
- # @example
41
- # Fear['[1, 2, _]'].failure_reason([1, 3, 4])
42
- # # it will show that the second element hasn't match
43
- #
44
- def failure_reason(other)
45
- if defined_at?(other)
46
- Fear.none
47
- else
48
- Fear.some("Expected `#{other.inspect}` to match:\n#{input}\n#{"~" * input_position}^")
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Match against array splat, and capture rest of an array
6
- # E.g. +[1, 2, *tail]+
7
- #
8
- class NamedArraySplatMatcher < ArraySplatMatcher
9
- # @!attribute name
10
- # @return [Types::Strict::Symbol]
11
-
12
- def bindings(other)
13
- { name => other }
14
- end
15
- end
16
- end
17
- end
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "lru_redux"
4
-
5
- module Fear
6
- module Extractor
7
- # Parse pattern. Used within +Fear[]+
8
- class Pattern
9
- DEFAULT_PATTERN_CACHE_SIZE = 10_000
10
- private_constant :DEFAULT_PATTERN_CACHE_SIZE
11
- @pattern_cache = LruRedux::Cache.new(ENV.fetch("FEAR_PATTERNS_CACHE_SIZE", DEFAULT_PATTERN_CACHE_SIZE))
12
-
13
- class << self
14
- attr_reader :pattern_cache
15
- end
16
-
17
- def initialize(pattern)
18
- @matcher = compile_pattern(pattern)
19
- end
20
- attr_reader :matcher
21
- private :matcher
22
-
23
- private def compile_pattern(pattern)
24
- self.class.pattern_cache.getset(pattern) do
25
- compile_pattern_without_cache(pattern)
26
- end
27
- end
28
-
29
- private def compile_pattern_without_cache(pattern)
30
- parser = Extractor::GrammarParser.new
31
- if (result = parser.parse(pattern))
32
- result.to_matcher
33
- else
34
- raise PatternSyntaxError, syntax_error_message(parser, pattern)
35
- end
36
- end
37
-
38
- def ===(other)
39
- matcher.defined_at?(other)
40
- end
41
-
42
- def and_then(other)
43
- Fear::PartialFunction::Combined.new(matcher, other)
44
- end
45
-
46
- def failure_reason(other)
47
- matcher.failure_reason(other).get_or_else { "It matches" }
48
- end
49
-
50
- private def syntax_error_message(parser, pattern)
51
- parser.failure_reason =~ /^(Expected .+) after/m
52
- "#{Regexp.last_match(1).gsub("\n", "$NEWLINE")}:\n" +
53
- pattern.split("\n")[parser.failure_line - 1] + "\n" \
54
- "#{"~" * (parser.failure_column - 1)}^\n"
55
- end
56
- end
57
- end
58
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Match and capture identifier with specific type. E.g. +foo : Integer+
6
- #
7
- class TypedIdentifierMatcher < Matcher
8
- # @!attribute identifier
9
- # @return [IdentifierMatcher]
10
- # @!attribute type
11
- # @return [ValueMatcher]
12
-
13
- def defined_at?(other)
14
- type.defined_at?(other)
15
- end
16
-
17
- def bindings(other)
18
- { identifier.name => other }
19
- end
20
-
21
- def failure_reason(other)
22
- type.failure_reason(other)
23
- end
24
- end
25
- end
26
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Match against values -- true, false, 1, "foo" etc.
6
- class ValueMatcher < Matcher
7
- # @!attribute value
8
- # @return [Any]
9
-
10
- def defined_at?(arg)
11
- value === arg
12
- end
13
-
14
- def bindings(_)
15
- Utils::EMPTY_HASH
16
- end
17
- end
18
- end
19
- end
@@ -1,112 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "treetop"
4
- require "fear/extractor/grammar"
5
- Treetop.load File.expand_path("extractor/grammar.treetop", __dir__)
6
-
7
- module Fear
8
- # @api private
9
- module Extractor
10
- autoload :Pattern, "fear/extractor/pattern"
11
- autoload :Matcher, "fear/extractor/matcher"
12
-
13
- autoload :AnonymousArraySplatMatcher, "fear/extractor/anonymous_array_splat_matcher"
14
- autoload :AnyMatcher, "fear/extractor/any_matcher"
15
- autoload :ArrayHeadMatcher, "fear/extractor/array_head_matcher"
16
- autoload :ArrayMatcher, "fear/extractor/array_matcher"
17
- autoload :ArraySplatMatcher, "fear/extractor/array_splat_matcher"
18
- autoload :EmptyListMatcher, "fear/extractor/empty_list_matcher"
19
- autoload :ExtractorMatcher, "fear/extractor/extractor_matcher"
20
- autoload :IdentifierMatcher, "fear/extractor/identifier_matcher"
21
- autoload :NamedArraySplatMatcher, "fear/extractor/named_array_splat_matcher"
22
- autoload :TypedIdentifierMatcher, "fear/extractor/typed_identifier_matcher"
23
- autoload :ValueMatcher, "fear/extractor/value_matcher"
24
-
25
- ExtractorNotFound = Class.new(Error)
26
- public_constant :ExtractorNotFound
27
-
28
- @mutex = Mutex.new
29
- @registry = PartialFunction::EMPTY
30
-
31
- EXTRACTOR_NOT_FOUND = proc do |klass|
32
- raise ExtractorNotFound, "could not find extractor for " + klass.inspect
33
- end
34
- private_constant :EXTRACTOR_NOT_FOUND
35
-
36
- class << self
37
- # @param klass [Class, String]
38
- # @api private
39
- def find_extractor(klass)
40
- @registry.call_or_else(klass, &EXTRACTOR_NOT_FOUND)
41
- end
42
-
43
- # Register extractor for given class
44
- # @!method register_extractor(*names, extractor)
45
- # @param names [<Class, String>, Class, String] name of a class. You can also pass alias for the name
46
- # @param extractor [Proc<any => Fear::Option>] proc taking any argument and returned Option
47
- # of extracted value('s)
48
- #
49
- # @example
50
- # register_extractor(Fear::Some, Fear.case(Fear::Some) { |some| some.get }.lift)
51
- #
52
- # register_extractor(User, Fear.case(User) { |user|} [user.id, user.email] , )
53
- #
54
- # @example registering an alias. Alias should be CamelCased string
55
- # register_extractor(Fear::Some, 'Some', Fear.case(Fear::Some) { |some| some.get }.lift)
56
- #
57
- # # no you can extract Fear::Some's using Some alias
58
- # m.case(Fear['Some(value : Integer)']) { |value:| value * 2 }
59
- #
60
- def register_extractor(*args)
61
- *keys, extractor = *args
62
-
63
- @mutex.synchronize do
64
- keys.uniq.each do |key|
65
- @registry = BUILD_EXTRACTOR.(key, extractor).or_else(@registry)
66
- end
67
- end
68
- self
69
- end
70
-
71
- BUILD_EXTRACTOR = proc do |key, extractor|
72
- Fear.matcher do |m|
73
- case key
74
- when String
75
- m.case(Module, ->(lookup) { lookup.to_s == key }) { extractor }
76
- m.case(String, key) { extractor }
77
- when Module
78
- m.case(Module, ->(lookup) { lookup <= key }) { extractor }
79
- m.case(String, key.to_s) { extractor }
80
- else
81
- m.case(key) { extractor } # may it be useful to register other types of keys? lambda?
82
- end
83
- end
84
- end
85
- end
86
-
87
- # Multiple arguments extractor example
88
- register_extractor("Date", proc do |other|
89
- if other.class.name == "Date"
90
- Fear.some([other.year, other.month, other.day])
91
- else
92
- Fear.none
93
- end
94
- end)
95
- register_extractor(::Struct, Fear.case(::Struct, &:to_a).lift)
96
- # No argument boolean extractor example
97
- register_extractor("IsEven", proc do |int|
98
- if int.is_a?(Integer) && int.even?
99
- Fear.some([])
100
- else
101
- Fear.none
102
- end
103
- end)
104
- # Single argument extractor example
105
- register_extractor("Fear::Some", "Some", Some::EXTRACTOR)
106
- register_extractor("Fear::None", "None", NoneClass::EXTRACTOR)
107
- register_extractor("Fear::Right", "Right", Right::EXTRACTOR)
108
- register_extractor("Fear::Left", "Left", Left::EXTRACTOR)
109
- register_extractor("Fear::Success", "Success", Success::EXTRACTOR)
110
- register_extractor("Fear::Failure", "Failure", Failure::EXTRACTOR)
111
- end
112
- end