Skip to content

Commit cb886a3

Browse files
committed
feat: add pattern matching by deconstruct
1 parent c3a6317 commit cb886a3

5 files changed

Lines changed: 75 additions & 6 deletions

File tree

.rubocop.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@ Layout/LineLength:
3939

4040
Lint/UnusedBlockArgument:
4141
Enabled: false
42+
43+
Style/ConditionalAssignment:
44+
EnforcedStyle: assign_to_condition

lib/rs/option.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ def ==(other)
183183
other.is_a?(Some) && @value == other.unwrap && @value_type == other.value_type
184184
end
185185

186+
def deconstruct
187+
[self, @value]
188+
end
189+
186190
def initialize(value)
187191
if value == nil
188192
raise WrapNil.new("Cannot create Some[T](value) with nil")
@@ -208,6 +212,10 @@ def ==(other)
208212
other.is_a?(None) && @value_type == other.value_type
209213
end
210214

215+
def deconstruct
216+
[self]
217+
end
218+
211219
def initialize(value_type = Class)
212220
if !value_type.is_a?(Class)
213221
raise TypeError.new(value_type)

lib/rs/result.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ def ==(other)
204204
other.is_a?(Ok) && @value == other.unwrap && @value_type == other.value_type && @error_type == other.error_type
205205
end
206206

207+
def deconstruct
208+
[self, @value]
209+
end
210+
207211
def initialize(value)
208212
if value == nil
209213
raise WrapNil.new("Cannot create Ok[T, E] with nil")
@@ -250,6 +254,10 @@ def ==(other)
250254
other.is_a?(Err) && @error == other.unwrap_err && @value_type == other.value_type && @error_type == other.error_type
251255
end
252256

257+
def deconstruct
258+
[self, @error]
259+
end
260+
253261
def initialize(error)
254262
if error == nil
255263
raise WrapNil.new("Cannot create Err[T, E] with nil")

spec/rs/option_spec.rb

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@
2727
expect(x).to eq y
2828
end
2929

30+
it "pattern matching" do
31+
x = Some.new(2)
32+
tx = case x
33+
in Some, Integer => i
34+
i
35+
in Some, Float => f
36+
f
37+
in None
38+
0
39+
end
40+
41+
expect(tx).to eq 2
42+
43+
x = None.new
44+
tx = case x
45+
in Some, any
46+
any
47+
in None
48+
0
49+
end
50+
51+
expect(tx).to eq 0
52+
end
53+
3054
it "is_some" do
3155
x = Some.new(2)
3256
expect(x.is_some).to be true
@@ -116,12 +140,12 @@ def divide(numerator, denominator)
116140
end
117141

118142
result = divide(3.0, 1.0)
119-
case result
120-
when Some
121-
x = result.unwrap
122-
else
123-
x = "Cannot divide by 0"
124-
end
143+
x = case result
144+
when Some
145+
result.unwrap
146+
else
147+
"Cannot divide by 0"
148+
end
125149
expect(x).to eq 3.0
126150
end
127151

spec/rs/result_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,32 @@
1919
expect { Err.new(nil) }.to raise_error Rs::Result::WrapNil
2020
end
2121

22+
it "pattern matching" do
23+
x = Ok[Float, String] { 2.0 }
24+
tx = case x
25+
in Ok, Integer => i
26+
i
27+
in Ok, Float => f
28+
f
29+
in Err, String => str
30+
str
31+
else
32+
"mismatch"
33+
end
34+
35+
expect(tx).to eq 2.0
36+
37+
x = Err[Float, String] { "foo" }
38+
tx = case x
39+
in Ok, any
40+
any
41+
in Err, str
42+
str
43+
end
44+
45+
expect(tx).to eq "foo"
46+
end
47+
2248
it "is_ok" do
2349
x = Ok.new(-3)
2450
expect(x.is_ok).to be true

0 commit comments

Comments
 (0)