deterministic 0.15.3 → 0.16.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 70b4013b20820efd41949d10c8bcb0706b514d12
4
- data.tar.gz: cdb7071c05a8001af91c10212a67eceede5106cb
3
+ metadata.gz: 7120823c22300ba01fd44a7a3d18aae96f7357ba
4
+ data.tar.gz: 8cd374ad1eed4bba6aae559d96730954d76b15bd
5
5
  SHA512:
6
- metadata.gz: 30b231a3e818e90d9f49fc5b9932adafe969ccfe8e645cabda707f2e5a13b50efd0e2f07916accb82c53f64e5dd592d85aa2075d21b1859a598c56a7ed9ba91b
7
- data.tar.gz: b81e77b351c2fb48c5debfc979db451e5f021bd7cf3d240d101e867e0ae6e9c65ceeb3dd285f88f7332fce58c68db8d0c906dd1734c16c229ba80964c6336de2
6
+ metadata.gz: 0a15bd39adfa6dd90d2a9f5f395aba58881bab0380b743770a5dc6d09bf87d4681b7ae7493f344a66ae771a4f084e898d853c3f9745c9b165df27d9a7b928c49
7
+ data.tar.gz: d0df2e74a8a941216a1a58b836916dd55e5ed15d90c3e93dcd22d611e20a3b041dbf7ed4c767ad47c08c38eab7e2ccc60c76c10a9290c7125bb32c5321a1dd71
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Deterministic is to help your code to be more confident, by utilizing functional programming patterns.
7
7
 
8
- This is a spiritual successor of the [Monadic gem](http://github.com/pzol/monadic). The goal of the rewrite is to get away from a bit to forceful aproach I took in Monadic, especially when it comes to coercing monads, but also a more practical but at the same time more strict adherence to monad laws.
8
+ This is a spiritual successor of the [Monadic gem](http://github.com/pzol/monadic). The goal of the rewrite is to get away from a bit too forceful aproach I took in Monadic, especially when it comes to coercing monads, but also a more practical but at the same time more strict adherence to monad laws.
9
9
 
10
10
  ## Patterns
11
11
 
@@ -213,29 +213,35 @@ Now that you have some result, you want to control flow by providing patterns.
213
213
 
214
214
  ```ruby
215
215
  Success(1).match do
216
- Success(s) { |v| "success #{s}"}
217
- Failure(f) { |v| "failure #{f}"}
216
+ Success() { |s| "success #{s}"}
217
+ Failure() { |f| "failure #{f}"}
218
218
  end # => "success 1"
219
219
  ```
220
- Note1: the inner value has been unwrapped!
220
+ Note1: the variant's inner value(s) have been unwrapped, and passed to the block.
221
221
 
222
222
  Note2: only the __first__ matching pattern block will be executed, so order __can__ be important.
223
223
 
224
+ Note3: you can omit block parameters if you don't use them, or you can use `_` to signify that you don't care about their values. If you specify parameters, their number must match the number of values in the variant.
225
+
224
226
  The result returned will be the result of the __first__ `#try` or `#let`. As a side note, `#try` is a monad, `#let` is a functor.
225
227
 
226
228
  Guards
227
229
 
228
230
  ```ruby
229
231
  Success(1).match do
230
- Success(s, where { s == 1 }) { "Success #{s}" }
232
+ Success(where { s == 1 }) { |s| "Success #{s}" }
231
233
  end # => "Success 1"
232
234
  ```
233
235
 
236
+ Note1: the guard has access to variable names defined by the block arguments.
237
+
238
+ Note2: the guard is not evaluated using the enclosing context's `self`; if you need to call methods on the enclosing scope, you must specify a receiver.
239
+
234
240
  Also you can match the result class
235
241
 
236
242
  ```ruby
237
243
  Success([1, 2, 3]).match do
238
- Success(s, where { s.is_a?(Array)} ) { s.first }
244
+ Success(where { s.is_a?(Array) }) { |s| s.first }
239
245
  end # => 1
240
246
  ```
241
247
 
@@ -243,7 +249,7 @@ If no match was found a `NoMatchError` is raised, so make sure you always cover
243
249
 
244
250
  ```ruby
245
251
  Success(1).match do
246
- Failure(f) { "you'll never get me" }
252
+ Failure() { |f| "you'll never get me" }
247
253
  end # => NoMatchError
248
254
  ```
249
255
 
@@ -323,9 +329,9 @@ Option.try! { raise "error"} # => None
323
329
  ### Pattern Matching
324
330
  ```ruby
325
331
  Some(1).match {
326
- Some(s, where { s == 1 }) { s + 1 }
327
- Some(s) { 1 }
328
- None() { 0 }
332
+ Some(where { s == 1 }) { |s| s + 1 }
333
+ Some() { |s| 1 }
334
+ None() { 0 }
329
335
  } # => 2
330
336
  ```
331
337
 
@@ -361,28 +367,28 @@ Pattern matching
361
367
 
362
368
  ```ruby
363
369
  Threenum::Unary(5).match {
364
- Nullary() { 0 }
365
- Unary(u) { u }
366
- Binary(a, b) { a + b }
370
+ Nullary() { 0 }
371
+ Unary() { |u| u }
372
+ Binary() { |a, b| a + b }
367
373
  } # => 5
368
374
 
369
375
  # or
370
376
  t = Threenum::Unary(5)
371
377
  Threenum.match(t) {
372
- Nullary() { 0 }
373
- Unary(u) { u }
374
- Binary(a, b) { a + b }
378
+ Nullary() { 0 }
379
+ Unary() { |u| u }
380
+ Binary() { |a, b| a + b }
375
381
  } # => 5
376
382
  ```
377
383
 
378
- If you want the whole thing use the arg passed to the block (second case)
384
+ If you want to return the whole matched object, you'll need to pass a reference to the object (second case). Note that `self` refers to the scope enclosing the `match` call.
379
385
 
380
386
  ```ruby
381
387
  def drop(n)
382
388
  match {
383
- Cons(h, t, where { n > 0 }) { t.drop(n - 1) }
384
- Cons(_, _) { |c| c }
385
- Nil() { raise EmptyListError}
389
+ Cons(where { n > 0 }) { |h, t| t.drop(n - 1) }
390
+ Cons() { |_, _| self }
391
+ Nil() { raise EmptyListError }
386
392
  }
387
393
  end
388
394
  ```
@@ -393,10 +399,10 @@ With guard clauses
393
399
 
394
400
  ```ruby
395
401
  Threenum::Unary(5).match {
396
- Nullary() { 0 }
397
- Unary(u) { u }
398
- Binary(a, b, where { a.is_a?(Fixnum) && b.is_a?(Fixnum)}) { a + b }
399
- Binary(a, b) { raise "Expected a, b to be numbers" }
402
+ Nullary() { 0 }
403
+ Unary() { |u| u }
404
+ Binary(where { a.is_a?(Fixnum) && b.is_a?(Fixnum) }) { |a, b| a + b }
405
+ Binary() { |a, b| raise "Expected a, b to be numbers" }
400
406
  } # => 5
401
407
  ```
402
408
 
@@ -406,17 +412,17 @@ Implementing methods for enums
406
412
  Deterministic::impl(Threenum) {
407
413
  def sum
408
414
  match {
409
- Nullary() { 0 }
410
- Unary(u) { u }
411
- Binary(a, b) { a + b }
415
+ Nullary() { 0 }
416
+ Unary() { |u| u }
417
+ Binary() { |a, b| a + b }
412
418
  }
413
419
  end
414
420
 
415
421
  def +(other)
416
422
  match {
417
- Nullary() { other.sum }
418
- Unary(a) { |this| this.sum + other.sum }
419
- Binary(a, b) { |this| this.sum + other.sum }
423
+ Nullary() { other.sum }
424
+ Unary() { |a| self.sum + other.sum }
425
+ Binary() { |a, b| self.sum + other.sum }
420
426
  }
421
427
  end
422
428
  }
@@ -23,6 +23,16 @@ module Deterministic
23
23
  def name
24
24
  self.class.name.split("::")[-1]
25
25
  end
26
+
27
+ # Returns array. Will fail on Nullary objects.
28
+ # TODO: define a Unary module so we can define this method differently on Unary vs Binary
29
+ def wrapped_values
30
+ if self.is_a?(Deterministic::EnumBuilder::DataType::Binary)
31
+ value.values
32
+ else
33
+ [value]
34
+ end
35
+ end
26
36
  end
27
37
 
28
38
  module Nullary
@@ -35,6 +45,7 @@ module Deterministic
35
45
  end
36
46
  end
37
47
 
48
+ # TODO: this should probably be named Multary
38
49
  module Binary
39
50
  def initialize(*init)
40
51
  raise ArgumentError, "Expected arguments for #{args}, got #{init}" unless (init.count == 1 && init[0].is_a?(Hash)) || init.count == args.count
@@ -103,6 +114,8 @@ module_function
103
114
  class << self; private :new; end
104
115
 
105
116
  def self.match(obj, &block)
117
+ caller_ctx = block.binding.eval 'self'
118
+
106
119
  matcher = self::Matcher.new(obj)
107
120
  matcher.instance_eval(&block)
108
121
 
@@ -116,17 +129,19 @@ module_function
116
129
  obj, type, block, args, guard = match
117
130
 
118
131
  if args.count == 0
119
- return instance_exec(obj, &block)
132
+ return caller_ctx.instance_eval(&block)
120
133
  else
121
- raise Enum::MatchError, "Pattern (#{args.join(', ')}) must match (#{obj.args.join(', ')})" if args.count != obj.args.count
122
- context = exec_context(obj, args)
134
+ if args.count != obj.args.count
135
+ raise Enum::MatchError, "Pattern (#{args.join(', ')}) must match (#{obj.args.join(', ')})"
136
+ end
137
+ guard_ctx = guard_context(obj, args)
123
138
 
124
139
  if guard
125
- if context.instance_exec(obj, &guard)
126
- return context.instance_exec(obj, &block)
140
+ if guard_ctx.instance_exec(obj, &guard)
141
+ return caller_ctx.instance_exec(* obj.wrapped_values, &block)
127
142
  end
128
143
  else
129
- return context.instance_exec(obj, &block)
144
+ return caller_ctx.instance_exec(* obj.wrapped_values, &block)
130
145
  end
131
146
  end
132
147
  }
@@ -137,7 +152,7 @@ module_function
137
152
  def self.variants; constants - [:Matcher, :MatchError]; end
138
153
 
139
154
  private
140
- def self.exec_context(obj, args)
155
+ def self.guard_context(obj, args)
141
156
  if obj.is_a?(Deterministic::EnumBuilder::DataType::Binary)
142
157
  Struct.new(*(args)).new(*(obj.value.values))
143
158
  else
@@ -163,17 +178,22 @@ module_function
163
178
  guard
164
179
  end
165
180
 
166
- def method_missing(m)
167
- m
168
- end
169
-
170
181
  type_variants.each { |m|
171
- define_method(m) { |*args, &block|
182
+ define_method(m) { |guard = nil, &block|
172
183
  raise ArgumentError, "No block given to `#{m}`" if block.nil?
184
+ params_spec = block.parameters
185
+ if params_spec.any? {|spec| spec.size < 2 }
186
+ raise ArgumentError, "Unnamed param found in block parameters: #{params_spec.inspect}"
187
+ end
188
+ if params_spec.any? {|spec| spec[0] != :req && spec[0] != :opt }
189
+ raise ArgumentError, "Only :req & :opt params allowed; parameters=#{params_spec.inspect}"
190
+ end
191
+ args = params_spec.map {|spec| spec[1] }
192
+
173
193
  type = Kernel.eval("#{mod.name}::#{m}")
174
194
 
175
- if args.count > 0 && args[-1].is_a?(Proc)
176
- guard = args.delete_at(-1)
195
+ if guard && !guard.is_a?(Proc)
196
+ guard = nil
177
197
  end
178
198
 
179
199
  @matches << [@obj, type, block, args, guard]
@@ -1,3 +1,4 @@
1
+ # TODO: remove dead code
1
2
  module Deterministic
2
3
  module PatternMatching
3
4
 
@@ -29,15 +29,15 @@ module Deterministic
29
29
 
30
30
  def fmap(&fn)
31
31
  match {
32
- Some(s) { |m| m.class.new(fn.(s)) }
33
- None() { |n| n }
32
+ Some() {|s| self.class.new(fn.(s)) }
33
+ None() { self }
34
34
  }
35
35
  end
36
36
 
37
37
  def map(&fn)
38
38
  match {
39
- Some(s) { |m| m.bind(&fn) }
40
- None() { |n| n }
39
+ Some() {|s| self.bind(&fn) }
40
+ None() { self }
41
41
  }
42
42
  end
43
43
 
@@ -53,8 +53,8 @@ module Deterministic
53
53
 
54
54
  def value_or(n)
55
55
  match {
56
- Some(s) { s }
57
- None() { n }
56
+ Some() {|s| s }
57
+ None() { n }
58
58
  }
59
59
  end
60
60
 
@@ -65,9 +65,9 @@ module Deterministic
65
65
  def +(other)
66
66
  match {
67
67
  None() { other }
68
- Some(_, where { !other.is_a?(Option)}) { raise TypeError, "Other must be an #{Option}"}
69
- Some(s, where { other.some? }) { Option::Some.new(s + other.value) }
70
- Some(_) { |s| s }
68
+ Some(where { !other.is_a?(Option) }) {|_| raise TypeError, "Other must be an #{Option}"}
69
+ Some(where { other.some? }) {|s| Option::Some.new(s + other.value) }
70
+ Some() {|_| self }
71
71
  }
72
72
  end
73
73
  }
@@ -19,8 +19,8 @@ module Deterministic
19
19
  Deterministic::impl(Result) {
20
20
  def map(proc=nil, &block)
21
21
  match {
22
- Success(_) { |s| s.bind(proc || block) }
23
- Failure(_) { |f| f }
22
+ Success() {|_| self.bind(proc || block) }
23
+ Failure() {|_| self }
24
24
  }
25
25
  end
26
26
 
@@ -29,8 +29,8 @@ module Deterministic
29
29
 
30
30
  def map_err(proc=nil, &block)
31
31
  match {
32
- Success(_) { |s| s }
33
- Failure(_) { |f| f.bind(proc|| block) }
32
+ Success() {|_| self }
33
+ Failure() {|_| self.bind(proc|| block) }
34
34
  }
35
35
  end
36
36
 
@@ -54,26 +54,26 @@ module Deterministic
54
54
  def or(other)
55
55
  raise Deterministic::Monad::NotMonadError, "Expected #{other.inspect} to be a Result" unless other.is_a? Result
56
56
  match {
57
- Success(_) { |s| s }
58
- Failure(_) { other}
57
+ Success() {|_| self }
58
+ Failure() {|_| other }
59
59
  }
60
60
  end
61
61
 
62
62
  def and(other)
63
63
  raise Deterministic::Monad::NotMonadError, "Expected #{other.inspect} to be a Result" unless other.is_a? Result
64
64
  match {
65
- Success(_) { other }
66
- Failure(_) { |f| f }
65
+ Success() {|_| other }
66
+ Failure() {|_| self }
67
67
  }
68
68
  end
69
69
 
70
70
  def +(other)
71
71
  raise Deterministic::Monad::NotMonadError, "Expected #{other.inspect} to be a Result" unless other.is_a? Result
72
72
  match {
73
- Success(s, where { other.success?} ) { Result::Success.new(s + other.value) }
74
- Failure(f, where { other.failure?} ) { Result::Failure.new(f + other.value) }
75
- Success(_) { other } # implied other.failure?
76
- Failure(_) { |f| f } # implied other.success?
73
+ Success(where { other.success? } ) {|s| Result::Success.new(s + other.value) }
74
+ Failure(where { other.failure? } ) {|f| Result::Failure.new(f + other.value) }
75
+ Success() {|_| other } # implied other.failure?
76
+ Failure() {|_| self } # implied other.success?
77
77
  }
78
78
  end
79
79
 
@@ -1,3 +1,3 @@
1
1
  module Deterministic
2
- VERSION = "0.15.3"
2
+ VERSION = "0.16.0"
3
3
  end
@@ -16,17 +16,17 @@ end
16
16
  Deterministic::impl(Amount) {
17
17
  def to_s
18
18
  match {
19
- Due(a) { "%0.2f" % [a] }
20
- Paid(a) { "-%0.2f" % [a] }
21
- Info(a) { "(%0.2f)" % [a] }
19
+ Due() {|a| "%0.2f" % [a] }
20
+ Paid() {|a| "-%0.2f" % [a] }
21
+ Info() {|a| "(%0.2f)" % [a] }
22
22
  }
23
23
  end
24
24
 
25
25
  def to_f
26
26
  match {
27
- Info(a) { 0 }
28
- Due(a) { a }
29
- Paid(a) { -1 * a }
27
+ Info() {|a| 0 }
28
+ Due() {|a| a }
29
+ Paid() {|a| -1 * a }
30
30
  }
31
31
  end
32
32
 
@@ -11,8 +11,8 @@ class ElasticSearchConfig
11
11
 
12
12
  def hosts
13
13
  Option.any?(proc_env["RESFINITY_LOG_CLIENT_ES_HOST"]).match {
14
- Some(s) { { hosts: s.split(/, */) } }
15
- None() { default_hosts }
14
+ Some() {|s| { hosts: s.split(/, */) } }
15
+ None() { default_hosts } # calls ElasticSearchConfig instance's method
16
16
  }
17
17
  end
18
18
 
@@ -31,7 +31,7 @@ private
31
31
  end
32
32
 
33
33
  describe ElasticSearchConfig do
34
- pending("match exec context must have access to parents block binding context") {
34
+ # NOTE: the "empty" cases also verify that the variant matchers use the enclosing context as self
35
35
 
36
36
  let(:cfg) { ElasticSearchConfig.new(environment, env) }
37
37
  context "test" do
@@ -72,5 +72,4 @@ describe ElasticSearchConfig do
72
72
  specify { expect(cfg.hosts).to eq({ hosts: ["acc.resfinity.net:9200"] }) }
73
73
  end
74
74
  end
75
- }
76
75
  end
@@ -28,46 +28,46 @@ Deterministic::impl(List) {
28
28
 
29
29
  def first
30
30
  match {
31
- Cons(_, _) { |c| c }
32
- Nil() { |n| n }
31
+ Cons() {|_, _| self }
32
+ Nil() { self }
33
33
  }
34
34
  end
35
35
 
36
36
  def last
37
37
  match {
38
- Cons(h, t, where { t.null? }) { |c| return c }
39
- Cons(_, t) { t.last }
40
- Nil() { |n| n }
38
+ Cons(where { t.null? }) {|h, t| return self }
39
+ Cons() {|_, t| t.last }
40
+ Nil() { self }
41
41
  }
42
42
  end
43
43
 
44
44
  def head
45
45
  match {
46
- Cons(h, _) { h }
47
- Nil() { |n| n }
46
+ Cons() {|h, _| h }
47
+ Nil() { self }
48
48
  }
49
49
  end
50
50
 
51
51
  def tail
52
52
  match {
53
- Cons(_, t) { t }
54
- Nil() { |n| raise EmptyListError }
53
+ Cons() { |_, t| t }
54
+ Nil() { raise EmptyListError }
55
55
  }
56
56
  end
57
57
 
58
58
  def init
59
59
  match {
60
- Cons(h, t, where { |c| t.tail.null? } ) { |c| Cons.new(h, Nil.new) }
61
- Cons(h, t) { |c| Cons.new(h, t.init) }
60
+ Cons(where { t.tail.null? } ) {|h, t| Cons.new(h, Nil.new) }
61
+ Cons() {|h, t| Cons.new(h, t.init) }
62
62
  Nil() { raise EmptyListError }
63
63
  }
64
64
  end
65
65
 
66
66
  def filter(&pred)
67
67
  match {
68
- Cons(h, t, where { pred.(h) }) { |c| Cons.new(h, t.filter(&pred)) }
69
- Cons(_, t) { t.filter(&pred) }
70
- Nil() { |n| n }
68
+ Cons(where { pred.(h) }) {|h, t| Cons.new(h, t.filter(&pred)) }
69
+ Cons() {|_, t| t.filter(&pred) }
70
+ Nil() { self }
71
71
  }
72
72
  end
73
73
 
@@ -76,21 +76,21 @@ Deterministic::impl(List) {
76
76
  def find(&pred)
77
77
  match {
78
78
  Nil() { Deterministic::Option::None.new }
79
- Cons(h, t) { if pred.(h) then Deterministic::Option::Some.new(h) else t.find(&pred) end }
79
+ Cons() {|h, t| pred.(h) ? Deterministic::Option::Some.new(h) : t.find(&pred) }
80
80
  }
81
81
  end
82
82
 
83
83
  def length
84
84
  match {
85
- Cons(h, t) { 1 + t.length }
85
+ Cons() {|h, t| 1 + t.length }
86
86
  Nil() { 0 }
87
87
  }
88
88
  end
89
89
 
90
90
  def map(&fn)
91
91
  match {
92
- Cons(h, t) { Cons.new(fn.(h), t.map(&fn)) }
93
- Nil() { |n| n }
92
+ Cons() {|h, t| Cons.new(fn.(h), t.map(&fn)) }
93
+ Nil() { self }
94
94
  }
95
95
  end
96
96
 
@@ -102,14 +102,14 @@ Deterministic::impl(List) {
102
102
  match {
103
103
  Nil() { start }
104
104
  # foldl f z (x:xs) = foldl f (f z x) xs
105
- Cons(h, t) { t.foldl(fn.(start, h), &fn) }
105
+ Cons() {|h, t| t.foldl(fn.(start, h), &fn) }
106
106
  }
107
107
  end
108
108
 
109
109
  def foldl1(&fn)
110
110
  match {
111
111
  Nil() { raise EmptyListError }
112
- Cons(h, t) { t.foldl(h, &fn)}
112
+ Cons() {|h, t| t.foldl(h, &fn)}
113
113
  }
114
114
  end
115
115
 
@@ -117,32 +117,32 @@ Deterministic::impl(List) {
117
117
  match {
118
118
  Nil() { start }
119
119
  # foldr f z (x:xs) = f x (foldr f z xs)
120
- Cons(h, t) { fn.(h, t.foldr(start, &fn)) }
120
+ Cons() {|h, t| fn.(h, t.foldr(start, &fn)) }
121
121
  }
122
122
  end
123
123
 
124
124
  def foldr1(&fn)
125
125
  match {
126
126
  Nil() { raise EmptyListError }
127
- Cons(h, t, where { t.null? }) { h }
127
+ Cons(where { t.null? }) {|h, t| h }
128
128
  # foldr1 f (x:xs) = f x (foldr1 f xs)
129
- Cons(h, t) { fn.(h, t.foldr1(&fn)) }
129
+ Cons() {|h, t| fn.(h, t.foldr1(&fn)) }
130
130
  }
131
131
  end
132
132
 
133
133
  def take(n)
134
134
  match {
135
- Cons(h, t, where { n > 0 }) { Cons.new(h, t.take(n - 1))}
136
- Cons(_, _) { Nil.new }
137
- Nil() { raise EmptyListError}
135
+ Cons(where { n > 0 }) {|h, t| Cons.new(h, t.take(n - 1)) }
136
+ Cons() {|_, _| Nil.new }
137
+ Nil() { raise EmptyListError }
138
138
  }
139
139
  end
140
140
 
141
141
  def drop(n)
142
142
  match {
143
- Cons(h, t, where { n > 0 }) { t.drop(n - 1) }
144
- Cons(_, _) { |c| c }
145
- Nil() { raise EmptyListError}
143
+ Cons(where { n > 0 }) {|h, t| t.drop(n - 1) }
144
+ Cons() {|_, _| self }
145
+ Nil() { raise EmptyListError }
146
146
  }
147
147
  end
148
148
 
@@ -153,31 +153,31 @@ Deterministic::impl(List) {
153
153
  def any?(&pred)
154
154
  match {
155
155
  Nil() { false }
156
- Cons(h, t, where { t.null? }) { pred.(h) }
157
- Cons(h, t) { pred.(h) || t.any?(&pred) }
156
+ Cons(where { t.null? }) {|h, t| pred.(h) }
157
+ Cons() {|h, t| pred.(h) || t.any?(&pred) }
158
158
  }
159
159
  end
160
160
 
161
161
  def all?(&pred)
162
162
  match {
163
163
  Nil() { false }
164
- Cons(h, t, where { t.null? }) { pred.(h) }
165
- Cons(h, t) { pred.(h) && t.all?(&pred) }
164
+ Cons(where { t.null? }) {|h, t| pred.(h) }
165
+ Cons() {|h, t| pred.(h) && t.all?(&pred) }
166
166
  }
167
167
  end
168
168
 
169
169
  def reverse
170
170
  match {
171
- Nil() { |n| n }
172
- Cons(_, t, where { t.null? }) { |c| c }
173
- Cons(h, t) { |c| Cons.new(c.last.head, c.init.reverse) }
171
+ Nil() { self }
172
+ Cons(where { t.null? }) {|_, t| self }
173
+ Cons() {|h, t| Cons.new(self.last.head, self.init.reverse) }
174
174
  }
175
175
  end
176
176
 
177
177
  def to_s(joiner = ", ")
178
178
  match {
179
179
  Nil() { "Nil" }
180
- Cons(head, tail) { head.to_s + joiner + tail.to_s }
180
+ Cons() {|head, tail| head.to_s + joiner + tail.to_s }
181
181
  }
182
182
  end
183
183
  }
@@ -13,9 +13,9 @@ describe List do
13
13
  it "catches ignores guards with non-matching clauses" do
14
14
  expect(
15
15
  list.match {
16
- Nil() { self }
17
- Cons(h, t, where { h == 0 }) { h }
18
- Cons(h, t) { h }
16
+ Nil() { list }
17
+ Cons(where { h == 0 }) {|h,t| h }
18
+ Cons() {|h, t| h }
19
19
  }).to eq 1
20
20
  end
21
21
 
@@ -23,15 +23,15 @@ describe List do
23
23
  expect( # guard catched
24
24
  list.match {
25
25
  Nil() { raise "unreachable" }
26
- Cons(h, t, where { h == 1 }) { h + 1 }
27
- Cons(h, t) { h }
26
+ Cons(where { h == 1 }) {|h,t| h + 1 }
27
+ Cons() {|h| h }
28
28
  }).to eq 2
29
29
  end
30
30
 
31
31
  it "raises an error when no match was made" do
32
32
  expect {
33
33
  list.match {
34
- Cons(_, _, where { true == false }) { 1 }
34
+ Cons(where { true == false }) {|_, _| 1 }
35
35
  Nil(where { true == false }) { 0 }
36
36
  }
37
37
  }.to raise_error(Deterministic::Enum::MatchError)
@@ -40,7 +40,7 @@ describe List do
40
40
  it "raises an error when the match is not exhaustive" do
41
41
  expect {
42
42
  list.match {
43
- Cons(_, _) {}
43
+ Cons() {|_, _| }
44
44
  }
45
45
  }.to raise_error(Deterministic::Enum::MatchError)
46
46
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
+ # TODO: dead code?
3
4
  class Logger
4
5
  alias :m :method
5
6
 
@@ -14,6 +15,7 @@ class Logger
14
15
  private
15
16
  attr_reader :repository
16
17
 
18
+ # TODO: this is never called; the matcher syntax is old
17
19
  def validate(item)
18
20
  return Failure(["Item cannot be empty"]) if item.blank?
19
21
  return Failure(["Item must be a Hash"]) unless item.is_a?(Hash)
@@ -75,8 +75,8 @@ describe Deterministic::Option do
75
75
  it "match" do
76
76
  expect(
77
77
  Some(0).match {
78
- Some(s, where { s == 1 } ) { |n| 99 }
79
- Some(s, where { s == 0 }) { |n| s + 1 }
78
+ Some(where { s == 1 }) {|s| 99 }
79
+ Some(where { s == 0 }) {|s| s + 1 }
80
80
  None() {}
81
81
  }
82
82
  ).to eq 1
@@ -84,14 +84,14 @@ describe Deterministic::Option do
84
84
  expect(
85
85
  Some(1).match {
86
86
  None() { 0 }
87
- Some(s) { 1 }
87
+ Some() {|s| 1 }
88
88
  }
89
89
  ).to eq 1
90
90
 
91
91
  expect(
92
92
  Some(1).match {
93
93
  None() { 0 }
94
- Some(s, where { s.is_a? Fixnum }) { 1 }
94
+ Some(where { s.is_a? Fixnum }) {|s| 1 }
95
95
  }
96
96
  ).to eq 1
97
97
 
@@ -27,7 +27,7 @@ describe Deterministic::Enum do
27
27
  expect(n).to be_a MyEnym
28
28
  expect(n).to be_a MyEnym::Nullary
29
29
  expect(n.name).to eq "Nullary"
30
- expect { n.value }.to raise_error
30
+ expect { n.value }.to raise_error NoMethodError
31
31
  expect(n.inspect).to eq "Nullary"
32
32
  expect(n.to_s).to eq ""
33
33
  expect(n.fmap { }).to eq n
@@ -77,8 +77,8 @@ describe Deterministic::Enum do
77
77
  res =
78
78
  MyEnym.match(b) {
79
79
  Nullary() { 0 }
80
- Unary(a) { [a, b] }
81
- Binary(x, y) { [x, y]}
80
+ Unary() {|a| a }
81
+ Binary() {|x,y| [x, y] }
82
82
  }
83
83
 
84
84
  expect(res).to eq [1, 2]
@@ -86,8 +86,8 @@ describe Deterministic::Enum do
86
86
  res =
87
87
  b.match {
88
88
  Nullary() { 0 }
89
- Unary(a) { [a, b] }
90
- Binary(x, y) { [x, y]}
89
+ Unary() {|a| a }
90
+ Binary() {|x,y| [x, y] }
91
91
  }
92
92
 
93
93
  expect(res).to eq [1, 2]
@@ -98,10 +98,10 @@ describe Deterministic::Enum do
98
98
  }.to raise_error(NameError)
99
99
 
100
100
  expect { b.match {
101
- Nullary()
102
- Unary()
103
- Binary()
104
- }
101
+ Nullary()
102
+ Unary()
103
+ Binary()
104
+ }
105
105
  }.to raise_error ArgumentError, "No block given to `Nullary`"
106
106
  end
107
107
  end
@@ -20,19 +20,18 @@ Threenum = Deterministic::enum {
20
20
 
21
21
  Deterministic::impl(Threenum) {
22
22
  def sum
23
-
24
23
  match {
25
- Nullary() { 0 }
26
- Unary(u) { u }
27
- Binary(a, b) { a + b }
24
+ Nullary() { 0 }
25
+ Unary() { |u| u }
26
+ Binary() { |a, b| a + b }
28
27
  }
29
28
  end
30
29
 
31
30
  def +(other)
32
31
  match {
33
- Nullary() { other.sum }
34
- Unary(a) { |this| this.sum + other.sum }
35
- Binary(a, b) { |this| this.sum + other.sum }
32
+ Nullary() { other.sum }
33
+ Unary() { |a| self.sum + other.sum }
34
+ Binary() { |a, b| self.sum + other.sum }
36
35
  }
37
36
  end
38
37
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deterministic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.3
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Zolnierek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-28 00:00:00.000000000 Z
11
+ date: 2016-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler