fear 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +27 -0
  3. data/.github/workflows/rubocop.yml +39 -0
  4. data/.github/workflows/spec.yml +42 -0
  5. data/.rubocop.yml +4 -60
  6. data/.simplecov +17 -0
  7. data/CHANGELOG.md +29 -1
  8. data/Gemfile +5 -5
  9. data/Gemfile.lock +86 -50
  10. data/README.md +240 -209
  11. data/Rakefile +72 -65
  12. data/examples/pattern_extracting.rb +10 -8
  13. data/examples/pattern_matching_binary_tree_set.rb +7 -2
  14. data/examples/pattern_matching_number_in_words.rb +48 -42
  15. data/fear.gemspec +33 -34
  16. data/lib/dry/types/fear/option.rb +125 -0
  17. data/lib/dry/types/fear.rb +8 -0
  18. data/lib/fear/await.rb +33 -0
  19. data/lib/fear/awaitable.rb +28 -0
  20. data/lib/fear/either.rb +15 -4
  21. data/lib/fear/either_api.rb +4 -0
  22. data/lib/fear/either_pattern_match.rb +9 -5
  23. data/lib/fear/empty_partial_function.rb +3 -1
  24. data/lib/fear/failure.rb +7 -7
  25. data/lib/fear/failure_pattern_match.rb +4 -0
  26. data/lib/fear/for.rb +4 -2
  27. data/lib/fear/for_api.rb +5 -1
  28. data/lib/fear/future.rb +157 -82
  29. data/lib/fear/future_api.rb +17 -4
  30. data/lib/fear/left.rb +3 -9
  31. data/lib/fear/left_pattern_match.rb +2 -0
  32. data/lib/fear/none.rb +28 -10
  33. data/lib/fear/none_pattern_match.rb +2 -0
  34. data/lib/fear/option.rb +30 -2
  35. data/lib/fear/option_api.rb +4 -0
  36. data/lib/fear/option_pattern_match.rb +8 -3
  37. data/lib/fear/partial_function/and_then.rb +4 -2
  38. data/lib/fear/partial_function/any.rb +2 -0
  39. data/lib/fear/partial_function/combined.rb +3 -1
  40. data/lib/fear/partial_function/empty.rb +6 -0
  41. data/lib/fear/partial_function/guard/and.rb +2 -0
  42. data/lib/fear/partial_function/guard/and3.rb +2 -0
  43. data/lib/fear/partial_function/guard/or.rb +2 -0
  44. data/lib/fear/partial_function/guard.rb +8 -6
  45. data/lib/fear/partial_function/lifted.rb +2 -0
  46. data/lib/fear/partial_function/or_else.rb +5 -1
  47. data/lib/fear/partial_function.rb +18 -9
  48. data/lib/fear/partial_function_class.rb +3 -1
  49. data/lib/fear/pattern_match.rb +3 -11
  50. data/lib/fear/pattern_matching_api.rb +6 -28
  51. data/lib/fear/promise.rb +7 -5
  52. data/lib/fear/right.rb +3 -9
  53. data/lib/fear/right_biased.rb +5 -3
  54. data/lib/fear/right_pattern_match.rb +4 -0
  55. data/lib/fear/some.rb +35 -8
  56. data/lib/fear/some_pattern_match.rb +2 -0
  57. data/lib/fear/struct.rb +237 -0
  58. data/lib/fear/success.rb +7 -8
  59. data/lib/fear/success_pattern_match.rb +4 -0
  60. data/lib/fear/try.rb +8 -2
  61. data/lib/fear/try_api.rb +4 -0
  62. data/lib/fear/try_pattern_match.rb +9 -5
  63. data/lib/fear/unit.rb +6 -2
  64. data/lib/fear/utils.rb +14 -2
  65. data/lib/fear/version.rb +4 -1
  66. data/lib/fear.rb +26 -44
  67. data/spec/dry/types/fear/option/constrained_spec.rb +22 -0
  68. data/spec/dry/types/fear/option/core_spec.rb +77 -0
  69. data/spec/dry/types/fear/option/default_spec.rb +21 -0
  70. data/spec/dry/types/fear/option/hash_spec.rb +58 -0
  71. data/spec/dry/types/fear/option/option_spec.rb +97 -0
  72. data/spec/fear/awaitable_spec.rb +19 -0
  73. data/spec/fear/done_spec.rb +7 -5
  74. data/spec/fear/either/mixin_spec.rb +4 -2
  75. data/spec/fear/either_pattern_match_spec.rb +10 -8
  76. data/spec/fear/either_pattern_matching_spec.rb +28 -0
  77. data/spec/fear/either_spec.rb +26 -0
  78. data/spec/fear/failure_spec.rb +57 -70
  79. data/spec/fear/for/mixin_spec.rb +15 -0
  80. data/spec/fear/for_spec.rb +19 -17
  81. data/spec/fear/future_spec.rb +477 -237
  82. data/spec/fear/guard_spec.rb +136 -24
  83. data/spec/fear/left_spec.rb +57 -70
  84. data/spec/fear/none_spec.rb +39 -43
  85. data/spec/fear/option/mixin_spec.rb +9 -7
  86. data/spec/fear/option_pattern_match_spec.rb +10 -8
  87. data/spec/fear/option_pattern_matching_spec.rb +34 -0
  88. data/spec/fear/option_spec.rb +142 -0
  89. data/spec/fear/partial_function/any_spec.rb +25 -0
  90. data/spec/fear/partial_function/empty_spec.rb +12 -10
  91. data/spec/fear/partial_function_and_then_spec.rb +39 -37
  92. data/spec/fear/partial_function_composition_spec.rb +46 -44
  93. data/spec/fear/partial_function_or_else_spec.rb +92 -90
  94. data/spec/fear/partial_function_spec.rb +91 -61
  95. data/spec/fear/pattern_match_spec.rb +19 -51
  96. data/spec/fear/pattern_matching_api_spec.rb +31 -0
  97. data/spec/fear/promise_spec.rb +23 -23
  98. data/spec/fear/right_biased/left.rb +28 -26
  99. data/spec/fear/right_biased/right.rb +51 -49
  100. data/spec/fear/right_spec.rb +48 -68
  101. data/spec/fear/some_spec.rb +30 -40
  102. data/spec/fear/success_spec.rb +40 -60
  103. data/spec/fear/try/mixin_spec.rb +19 -3
  104. data/spec/fear/try_api_spec.rb +23 -0
  105. data/spec/fear/try_pattern_match_spec.rb +10 -8
  106. data/spec/fear/try_pattern_matching_spec.rb +34 -0
  107. data/spec/fear/utils_spec.rb +16 -14
  108. data/spec/spec_helper.rb +13 -7
  109. data/spec/struct_pattern_matching_spec.rb +36 -0
  110. data/spec/struct_spec.rb +194 -0
  111. data/spec/support/dry_types.rb +6 -0
  112. metadata +128 -87
  113. data/.travis.yml +0 -13
  114. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -8
  115. data/lib/fear/extractor/any_matcher.rb +0 -15
  116. data/lib/fear/extractor/array_head_matcher.rb +0 -34
  117. data/lib/fear/extractor/array_matcher.rb +0 -38
  118. data/lib/fear/extractor/array_splat_matcher.rb +0 -14
  119. data/lib/fear/extractor/empty_list_matcher.rb +0 -18
  120. data/lib/fear/extractor/extractor_matcher.rb +0 -42
  121. data/lib/fear/extractor/grammar.rb +0 -201
  122. data/lib/fear/extractor/grammar.treetop +0 -129
  123. data/lib/fear/extractor/identifier_matcher.rb +0 -16
  124. data/lib/fear/extractor/matcher/and.rb +0 -36
  125. data/lib/fear/extractor/matcher.rb +0 -54
  126. data/lib/fear/extractor/named_array_splat_matcher.rb +0 -15
  127. data/lib/fear/extractor/pattern.rb +0 -55
  128. data/lib/fear/extractor/typed_identifier_matcher.rb +0 -24
  129. data/lib/fear/extractor/value_matcher.rb +0 -17
  130. data/lib/fear/extractor.rb +0 -108
  131. data/lib/fear/extractor_api.rb +0 -33
  132. data/spec/fear/extractor/array_matcher_spec.rb +0 -228
  133. data/spec/fear/extractor/extractor_matcher_spec.rb +0 -151
  134. data/spec/fear/extractor/grammar_array_spec.rb +0 -23
  135. data/spec/fear/extractor/identified_matcher_spec.rb +0 -47
  136. data/spec/fear/extractor/identifier_matcher_spec.rb +0 -66
  137. data/spec/fear/extractor/pattern_spec.rb +0 -32
  138. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -62
  139. data/spec/fear/extractor/value_matcher_number_spec.rb +0 -77
  140. data/spec/fear/extractor/value_matcher_string_spec.rb +0 -86
  141. data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -69
  142. data/spec/fear/extractor_api_spec.rb +0 -113
  143. data/spec/fear/extractor_spec.rb +0 -59
data/Rakefile CHANGED
@@ -1,28 +1,30 @@
1
- require 'bundler/gem_tasks'
2
- require 'benchmark/ips'
3
- require_relative 'lib/fear'
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "benchmark/ips"
5
+ require_relative "lib/fear"
4
6
 
5
7
  namespace :perf do
6
8
  # Contains benchmarking against Dry-rb
7
9
  namespace :dry do
8
10
  task :some_fmap_vs_fear_some_map do
9
- require 'dry/monads/maybe'
11
+ require "dry/monads/maybe"
10
12
 
11
13
  dry = Dry::Monads::Some.new(42)
12
14
  fear = Fear.some(42)
13
15
 
14
16
  Benchmark.ips do |x|
15
- x.report('Dry') { dry.fmap(&:itself) }
17
+ x.report("Dry") { dry.fmap(&:itself) }
16
18
 
17
- x.report('Fear') { fear.map(&:itself) }
19
+ x.report("Fear") { fear.map(&:itself) }
18
20
 
19
21
  x.compare!
20
22
  end
21
23
  end
22
24
 
23
25
  task :do_vs_fear_for do
24
- require 'dry/monads/maybe'
25
- require 'dry/monads/do'
26
+ require "dry/monads/maybe"
27
+ require "dry/monads/do"
26
28
 
27
29
  class Operation
28
30
  include Dry::Monads::Maybe::Mixin
@@ -42,9 +44,9 @@ namespace :perf do
42
44
  op = Operation.new
43
45
 
44
46
  Benchmark.ips do |x|
45
- x.report('Dry') { op.call }
47
+ x.report("Dry") { op.() }
46
48
 
47
- x.report('Fear') do |_n|
49
+ x.report("Fear") do |_n|
48
50
  Fear.for(Fear.some(1), Fear.some(2)) do |one, two|
49
51
  one + two
50
52
  end
@@ -58,21 +60,21 @@ namespace :perf do
58
60
  # Contains internal benchmarking to if optimization works
59
61
  namespace :fear do
60
62
  task :fear_pattern_extracting_with_vs_without_cache do
61
- some = Fear.some([:err, 'not found'])
63
+ some = Fear.some([:err, "not found"])
62
64
 
63
65
  class WOCache < Fear::Extractor::Pattern
64
66
  def initialize(pattern)
65
67
  @matcher = compile_pattern_without_cache(pattern)
66
68
  end
67
69
  end
68
- pattern = 'Fear::Some([:err, code])'
70
+ pattern = "Fear::Some([:err, code])"
69
71
 
70
72
  Benchmark.ips do |x|
71
- x.report('With cache') do |_n|
73
+ x.report("With cache") do |_n|
72
74
  Fear::Extractor::Pattern.new(pattern).extracted_arguments(some)
73
75
  end
74
76
 
75
- x.report('Without cache') do |_n|
77
+ x.report("Without cache") do |_n|
76
78
  WOCache.new(pattern).extracted_arguments(some)
77
79
  end
78
80
 
@@ -85,11 +87,11 @@ namespace :perf do
85
87
  condition = Integer
86
88
 
87
89
  Benchmark.ips do |x|
88
- x.report('Guard.new') do |n|
90
+ x.report("Guard.new") do |n|
89
91
  Fear::PartialFunction::Guard.new(condition) === n
90
92
  end
91
93
 
92
- x.report('Guard.and1') do |n|
94
+ x.report("Guard.and1") do |n|
93
95
  Fear::PartialFunction::Guard.and1(condition) === n
94
96
  end
95
97
 
@@ -105,11 +107,11 @@ namespace :perf do
105
107
  and_and = Fear::PartialFunction::Guard.new(first).and(Fear::PartialFunction::Guard.new(second))
106
108
 
107
109
  Benchmark.ips do |x|
108
- x.report('and2') do |n|
110
+ x.report("and2") do |n|
109
111
  and2 === n
110
112
  end
111
113
 
112
- x.report('Guard#and') do |n|
114
+ x.report("Guard#and") do |n|
113
115
  and_and === n
114
116
  end
115
117
 
@@ -120,7 +122,7 @@ namespace :perf do
120
122
  task :and3_vs_and_and do
121
123
  first = Integer
122
124
  second = ->(x) { x > 2 }
123
- third = ->(x) { x < 10 }
125
+ third = ->(x) { x < 10 }
124
126
 
125
127
  and3 = Fear::PartialFunction::Guard.and3(first, second, third)
126
128
 
@@ -129,11 +131,11 @@ namespace :perf do
129
131
  .and(Fear::PartialFunction::Guard.new(third))
130
132
 
131
133
  Benchmark.ips do |x|
132
- x.report('Guard.and3') do |n|
134
+ x.report("Guard.and3") do |n|
133
135
  and3 === n
134
136
  end
135
137
 
136
- x.report('Guard#and') do |n|
138
+ x.report("Guard#and") do |n|
137
139
  and_and_and === n
138
140
  end
139
141
 
@@ -149,15 +151,15 @@ namespace :perf do
149
151
  end
150
152
 
151
153
  Benchmark.ips do |x|
152
- x.report('construction') do
154
+ x.report("construction") do
153
155
  Fear::PatternMatch.new do |m|
154
156
  m.case(Integer) { |y| y * 2 }
155
157
  m.case(String) { |y| y.to_i(10) * 2 }
156
158
  end
157
159
  end
158
160
 
159
- x.report('execution') do
160
- matcher.call(42)
161
+ x.report("execution") do
162
+ matcher.(42)
161
163
  end
162
164
 
163
165
  x.compare!
@@ -166,23 +168,29 @@ namespace :perf do
166
168
  end
167
169
 
168
170
  namespace :pattern_matching do
169
- require 'qo'
170
- require 'dry/matcher'
171
+ require "qo"
172
+ require "dry/matcher"
171
173
 
172
- task :qo_vs_fear_pattern_extraction do
173
- User = Struct.new(:id, :name)
174
- user = User.new(42, 'Jane')
174
+ task :option_match_vs_native_pattern_match do
175
+ some = Fear.some(42)
175
176
 
176
177
  Benchmark.ips do |x|
177
- x.report('Qo') do
178
- Qo.case(user, destructure: true) do |m|
179
- m.when(User) { |id, name| [id, name] }
178
+ x.report("case ... in ...") do
179
+ case some
180
+ in Fear::Some(41 => x)
181
+ x
182
+ in Fear::Some(42 => x)
183
+ x
184
+ in Fear::Some(43 => x)
185
+ x
180
186
  end
181
187
  end
182
188
 
183
- x.report('Fear') do
184
- Fear.match(user) do |m|
185
- m.xcase('User(id, name)') { |id:, name:| [id, name] }
189
+ x.report("Option.match") do
190
+ some.match do |m|
191
+ m.some(41, &:itself)
192
+ m.some(42, &:itself)
193
+ m.some(45, &:itself)
186
194
  end
187
195
  end
188
196
 
@@ -198,25 +206,24 @@ namespace :perf do
198
206
  end
199
207
  end
200
208
 
201
- SuccessBranch = Qo.create_branch(name: 'success', precondition: Fear::Success, extractor: :get)
202
- FailureBranch = Qo.create_branch(name: 'failure', precondition: Fear::Failure, extractor: :exception)
209
+ SuccessBranch = Qo.create_branch(name: "success", precondition: Fear::Success, extractor: :get)
210
+ FailureBranch = Qo.create_branch(name: "failure", precondition: Fear::Failure, extractor: :exception)
203
211
 
204
212
  PatternMatch = Qo.create_pattern_match(
205
- branches: [SuccessBranch,
206
- FailureBranch],
213
+ branches: [SuccessBranch, FailureBranch],
207
214
  ).prepend(ExhaustivePatternMatch)
208
215
 
209
216
  Fear::Success.include(PatternMatch.mixin(as: :qo_match))
210
217
 
211
218
  success_case = Dry::Matcher::Case.new(
212
- match: lambda { |try, *pattern|
219
+ match: ->(try, *pattern) {
213
220
  try.is_a?(Fear::Success) && pattern.all? { |p| p === try.get }
214
221
  },
215
222
  resolve: ->(try) { try.get },
216
223
  )
217
224
 
218
225
  failure_case = Dry::Matcher::Case.new(
219
- match: lambda { |try, *pattern|
226
+ match: ->(try, *pattern) {
220
227
  try.is_a?(Fear::Failure) && pattern.all? { |p| p === try.exception }
221
228
  },
222
229
  resolve: ->(value) { value.exception },
@@ -228,27 +235,27 @@ namespace :perf do
228
235
  success = Fear::Success.new(4)
229
236
 
230
237
  Benchmark.ips do |x|
231
- x.report('Qo') do
238
+ x.report("Qo") do
232
239
  success.qo_match do |m|
233
240
  m.failure(&:itself)
234
241
  m.success(Integer, ->(y) { y % 5 == 0 }, &:itself)
235
- m.success { 'else' }
242
+ m.success { "else" }
236
243
  end
237
244
  end
238
245
 
239
- x.report('Fear') do
246
+ x.report("Fear") do
240
247
  success.match do |m|
241
248
  m.failure(&:itself)
242
249
  m.success(Integer, ->(y) { y % 5 == 0 }, &:itself)
243
- m.success { 'else' }
250
+ m.success { "else" }
244
251
  end
245
252
  end
246
253
 
247
- x.report('Dr::Matcher') do
248
- matcher.call(success) do |m|
254
+ x.report("Dr::Matcher") do
255
+ matcher.(success) do |m|
249
256
  m.failure(&:itself)
250
257
  m.success(Integer, ->(y) { y % 5 == 0 }, &:itself)
251
- m.success { 'else' }
258
+ m.success { "else" }
252
259
  end
253
260
  end
254
261
 
@@ -264,8 +271,8 @@ namespace :perf do
264
271
  end
265
272
  end
266
273
 
267
- SuccessBranch = Qo.create_branch(name: 'success', precondition: Fear::Success, extractor: :get)
268
- FailureBranch = Qo.create_branch(name: 'failure', precondition: Fear::Failure, extractor: :exception)
274
+ SuccessBranch = Qo.create_branch(name: "success", precondition: Fear::Success, extractor: :get)
275
+ FailureBranch = Qo.create_branch(name: "failure", precondition: Fear::Failure, extractor: :exception)
269
276
 
270
277
  QoPatternMatch = Qo.create_pattern_match(
271
278
  branches: [SuccessBranch, FailureBranch],
@@ -278,22 +285,22 @@ namespace :perf do
278
285
  qo_matcher = QoPatternMatch.new do |m|
279
286
  m.success(1, &:itself)
280
287
  m.success(4, &:itself)
281
- m.failure { 'failure' }
288
+ m.failure { "failure" }
282
289
  end
283
290
 
284
291
  fear_matcher = Fear::TryPatternMatch.new do |m|
285
292
  m.success(1, &:itself)
286
293
  m.success(4, &:itself)
287
- m.failure { 'failure' }
294
+ m.failure { "failure" }
288
295
  end
289
296
 
290
297
  Benchmark.ips do |x|
291
- x.report('Qo') do
292
- qo_matcher.call(success)
298
+ x.report("Qo") do
299
+ qo_matcher.(success)
293
300
  end
294
301
 
295
- x.report('Fear') do
296
- fear_matcher.call(success)
302
+ x.report("Fear") do
303
+ fear_matcher.(success)
297
304
  end
298
305
 
299
306
  x.compare!
@@ -305,33 +312,33 @@ namespace :perf do
305
312
  if n <= 1
306
313
  1
307
314
  else
308
- n * factorial_proc.call(n - 1)
315
+ n * factorial_proc.(n - 1)
309
316
  end
310
317
  end
311
318
 
312
319
  factorial_pm = Fear.matcher do |m|
313
320
  m.case(1, &:itself)
314
321
  m.case(0, &:itself)
315
- m.else { |n| n * factorial_pm.call(n - 1) }
322
+ m.else { |n| n * factorial_pm.(n - 1) }
316
323
  end
317
324
 
318
325
  factorial_qo = Qo.match do |m|
319
326
  m.when(1, &:itself)
320
327
  m.when(0, &:itself)
321
- m.else { |n| n * factorial_qo.call(n - 1) }
328
+ m.else { |n| n * factorial_qo.(n - 1) }
322
329
  end
323
330
 
324
331
  Benchmark.ips do |x|
325
- x.report('Proc') do
326
- factorial_proc.call(100)
332
+ x.report("Proc") do
333
+ factorial_proc.(100)
327
334
  end
328
335
 
329
- x.report('Fear') do
330
- factorial_pm.call(100)
336
+ x.report("Fear") do
337
+ factorial_pm.(100)
331
338
  end
332
339
 
333
- x.report('Qo') do
334
- factorial_qo.call(100)
340
+ x.report("Qo") do
341
+ factorial_qo.(100)
335
342
  end
336
343
 
337
344
  x.compare!
@@ -1,15 +1,17 @@
1
- require 'fear'
1
+ # frozen_string_literal: true
2
+
3
+ require "fear"
2
4
 
3
5
  User = Struct.new(:id, :name, :admin)
4
6
 
5
- matcher = Fear.matcher do |m|
6
- m.xcase('User(_, name, true)') do |name:|
7
+ matcher = proc do |value|
8
+ case value
9
+ in User(admin: true, name:)
7
10
  puts "Hi #{name}, you are welcome"
8
- end
9
- m.xcase('User(_, _, false)') do
10
- puts 'Only admins allowed here'
11
+ in User(admin: false)
12
+ puts "Only admins are allowed here"
11
13
  end
12
14
  end
13
15
 
14
- matcher.call User.new(1, 'Jane', true)
15
- matcher.call User.new(1, 'John', false)
16
+ matcher.(User.new(1, "Jane", true))
17
+ matcher.(User.new(1, "John", false))
@@ -1,4 +1,6 @@
1
- require 'fear'
1
+ # frozen_string_literal: true
2
+
3
+ require "fear"
2
4
 
3
5
  # @example Usage
4
6
  # set = BinaryTreeSet.new
@@ -10,8 +12,11 @@ require 'fear'
10
12
  #
11
13
  class BinaryTreeSet
12
14
  Position = Module.new
15
+ private_constant(:Position)
13
16
  Right = Module.new.include(Position)
17
+ private_constant(:Right)
14
18
  Left = Module.new.include(Position)
19
+ private_constant(:Left)
15
20
 
16
21
  def initialize(elem = 0, removed: true)
17
22
  @elem = elem
@@ -87,7 +92,7 @@ class BinaryTreeSet
87
92
  # @param position [Position]
88
93
  # @return [Fear::Option<BinaryTreeSet>]
89
94
  private def leaf(position)
90
- if subtrees.key?(position)
95
+ if subtrees.has_key?(position)
91
96
  Fear.some(subtrees[position])
92
97
  else
93
98
  Fear.none
@@ -1,54 +1,60 @@
1
- require 'fear'
1
+ # frozen_string_literal: true
2
+
3
+ require "fear"
2
4
 
3
5
  class ToWords
6
+ NUMBERS = {
7
+ 0 => "zero",
8
+ 1 => "one",
9
+ 2 => "two",
10
+ 3 => "three",
11
+ 4 => "four",
12
+ 5 => "five",
13
+ 6 => "six",
14
+ 7 => "seven",
15
+ 8 => "eight",
16
+ 9 => "nine",
17
+ 10 => "ten",
18
+ 11 => "eleven",
19
+ 12 => "twelve",
20
+ 13 => "thirteen",
21
+ 14 => "fourteen",
22
+ 15 => "fifteen",
23
+ 16 => "sixteen",
24
+ 17 => "seventeen",
25
+ 18 => "eighteen",
26
+ 19 => "nineteen",
27
+ 20 => "twenty",
28
+ 30 => "thirty",
29
+ 40 => "forty",
30
+ 50 => "fifty",
31
+ 60 => "sixty",
32
+ 70 => "seventy",
33
+ 80 => "eighty",
34
+ 90 => "ninety",
35
+ }.freeze
36
+ private_constant :NUMBERS
37
+
4
38
  CONVERTER = Fear.matcher do |m|
5
- {
6
- 0 => 'zero',
7
- 1 => 'one',
8
- 2 => 'two',
9
- 3 => 'three',
10
- 4 => 'four',
11
- 5 => 'five',
12
- 6 => 'six',
13
- 7 => 'seven',
14
- 8 => 'eight',
15
- 9 => 'nine',
16
- 10 => 'ten',
17
- 11 => 'eleven',
18
- 12 => 'twelve',
19
- 13 => 'thirteen',
20
- 14 => 'fourteen',
21
- 15 => 'fifteen',
22
- 16 => 'sixteen',
23
- 17 => 'seventeen',
24
- 18 => 'eighteen',
25
- 19 => 'nineteen',
26
- 20 => 'twenty',
27
- 30 => 'thirty',
28
- 40 => 'forty',
29
- 50 => 'fifty',
30
- 60 => 'sixty',
31
- 70 => 'seventy',
32
- 80 => 'eighty',
33
- 90 => 'ninety',
34
- }.each_pair do |number, in_words|
39
+ NUMBERS.each_pair do |number, in_words|
35
40
  m.case(number) { in_words }
36
41
  end
37
- m.case(->(n) { n < 0 }) { |n| "minus #{CONVERTER.call(-n)}" }
38
- m.case(->(n) { n < 100 }) { |n| "#{CONVERTER.call((n / 10) * 10)}-#{CONVERTER.call(n % 10)}" }
39
- m.case(->(n) { n < 200 }) { |n| "one hundred #{CONVERTER.call(n % 100)}" }
40
- m.case(->(n) { n < 1_000 }) { |n| "#{CONVERTER.call(n / 100)} hundreds #{CONVERTER.call(n % 100)}" }
41
- m.case(->(n) { n < 2_000 }) { |n| "one thousand #{CONVERTER.call(n % 1000)}" }
42
- m.case(->(n) { n < 1_000_000 }) { |n| "#{CONVERTER.call(n / 1_000)} thousands #{CONVERTER.call(n % 1_000)}" }
42
+ m.case(->(n) { n < 0 }) { |n| "minus #{CONVERTER.(-n)}" }
43
+ m.case(->(n) { n < 100 }) { |n| "#{CONVERTER.((n / 10) * 10)}-#{CONVERTER.(n % 10)}" }
44
+ m.case(->(n) { n < 200 }) { |n| "one hundred #{CONVERTER.(n % 100)}" }
45
+ m.case(->(n) { n < 1_000 }) { |n| "#{CONVERTER.(n / 100)} hundreds #{CONVERTER.(n % 100)}" }
46
+ m.case(->(n) { n < 2_000 }) { |n| "one thousand #{CONVERTER.(n % 1000)}" }
47
+ m.case(->(n) { n < 1_000_000 }) { |n| "#{CONVERTER.(n / 1_000)} thousands #{CONVERTER.(n % 1_000)}" }
43
48
  m.else { |n| raise "#{n} too big " }
44
49
  end
50
+ private_constant :CONVERTER
45
51
 
46
52
  def self.call(number)
47
- Fear.case(Integer, &:itself).and_then(CONVERTER).call(number)
53
+ Fear.case(Integer, &:itself).and_then(CONVERTER).(number)
48
54
  end
49
55
  end
50
56
 
51
- ToWords.call(99) #=> 'ninety-nine'
52
- ToWords.call(133) #=> 'one hundred thirty-three
53
- ToWords.call(777) #=> 'seven hundreds seventy-seven'
54
- ToWords.call(254_555) #=> 'two hundreds fifty-four thousands five hundreds fifty-five'
57
+ ToWords.(99) #=> 'ninety-nine'
58
+ ToWords.(133) #=> 'one hundred thirty-three
59
+ ToWords.(777) #=> 'seven hundreds seventy-seven'
60
+ ToWords.(254_555) #=> 'two hundreds fifty-four thousands five hundreds fifty-five'
data/fear.gemspec CHANGED
@@ -1,41 +1,40 @@
1
- lib = File.expand_path('lib', __dir__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
2
4
 
3
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
 
5
- require 'fear/version'
7
+ require "fear/version"
6
8
  Gem::Specification.new do |spec|
7
- spec.name = 'fear'
8
- spec.version = Fear::VERSION
9
- spec.authors = ['Tema Bolshakov']
10
- spec.email = ['abolshakov@spbtv.com']
11
- spec.summary = "%q{Ruby port of some Scala's monads.}"
12
- spec.description = "Ruby port of some Scala's monads."
13
- spec.homepage = 'https://github.com/bolshakov/fear'
14
- spec.license = 'MIT'
15
-
16
- spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin\/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^spec\/})
19
- spec.require_paths = ['lib']
20
-
21
- spec.post_install_message = <<-MSG
22
- Fear v0.11.0 introduces backwards-incompatible changes.
23
- Please see https://github.com/bolshakov/fear/blob/master/CHANGELOG.md#0110 for details.
24
- Successfully installed fear-#{Fear::VERSION}
25
- MSG
9
+ spec.name = "fear"
10
+ spec.version = Fear::VERSION
11
+ spec.authors = ["Tema Bolshakov"]
12
+ spec.email = ["abolshakov@spbtv.com"]
13
+ spec.summary = "%q{Ruby port of some Scala's monads.}"
14
+ spec.description = "Ruby port of some Scala's monads."
15
+ spec.homepage = "https://github.com/bolshakov/fear"
16
+ spec.license = "MIT"
26
17
 
27
- spec.add_runtime_dependency 'lru_redux'
28
- spec.add_runtime_dependency 'treetop'
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.executables = spec.files.grep(%r{^bin\/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^spec\/})
21
+ spec.require_paths = ["lib"]
22
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
29
23
 
30
- spec.add_development_dependency 'benchmark-ips'
31
- spec.add_development_dependency 'bundler'
32
- spec.add_development_dependency 'concurrent-ruby'
33
- spec.add_development_dependency 'dry-matcher'
34
- spec.add_development_dependency 'dry-monads'
35
- spec.add_development_dependency 'qo'
36
- spec.add_development_dependency 'rake', '~> 10.0'
37
- spec.add_development_dependency 'rspec', '~> 3.1'
38
- spec.add_development_dependency 'rubocop', '0.65.0'
39
- spec.add_development_dependency 'rubocop-rspec', '1.32.0'
40
- spec.add_development_dependency 'yard'
24
+ spec.add_development_dependency "benchmark-ips"
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "concurrent-ruby"
27
+ spec.add_development_dependency "dry-matcher"
28
+ spec.add_development_dependency "dry-monads"
29
+ spec.add_development_dependency "qo"
30
+ spec.add_development_dependency "rake", "~> 13.0"
31
+ spec.add_development_dependency "rspec", "~> 3.1"
32
+ spec.add_development_dependency "rubocop-rspec", "1.34.0"
33
+ spec.add_development_dependency "rubocop", "1.32.0"
34
+ spec.add_development_dependency "ruby_coding_standard"
35
+ spec.add_development_dependency "yard"
36
+ spec.add_development_dependency "dry-types"
37
+ spec.add_development_dependency "fear-rspec"
38
+ spec.add_development_dependency "simplecov"
39
+ spec.add_development_dependency "simplecov-lcov"
41
40
  end