Skip to content

Commit 05ec5f8

Browse files
committed
feat: include Comparable module, add test for it
1 parent 94444ee commit 05ec5f8

File tree

4 files changed

+74
-4
lines changed

4 files changed

+74
-4
lines changed

spec/option_spec.cr

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,4 +238,15 @@ describe Option do
238238
Option.from!(env_user).should eq(Some[%x(whoami).chomp])
239239
Option.from!(env_not_existing).should eq(None(String)[])
240240
end
241+
242+
it "<=>" do
243+
a = None(Int32)[]
244+
b = Some[0]
245+
c = Some[1]
246+
d = Some[1]
247+
248+
(a < b).should be_true
249+
(b < c).should be_true
250+
(c == d).should be_true
251+
end
241252
end

spec/result_spec.cr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,19 @@ describe Result do
236236
Result.from_or!(-> { ENV["USER"] }, false).should eq(Ok(String, Bool)[%x(whoami).chomp])
237237
Result.from_or!(-> { ENV["NOT_EXISTING"] }, false).should eq(Err(String, Bool)[false])
238238
end
239+
240+
it "<=>" do
241+
x1 = Ok(Int32, String)[1]
242+
y1 = Err(Int32, String)["error"]
243+
(x1 < y1).should be_true
244+
(y1 < x1).should be_false
245+
246+
x2 = Ok(Int32, String)[0]
247+
y2 = Ok(Int32, String)[1]
248+
(x2 < y2).should be_true
249+
250+
x3 = Err(Int32, Int32)[0]
251+
y3 = Err(Int32, Int32)[1]
252+
(x3 < y3).should be_true
253+
end
239254
end

src/option.cr

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ abstract struct Option(T)
55

66
class UnwrapNone < Exception; end
77

8+
class Uncomparable < Exception; end
9+
810
macro inherited
911
{% type = @type.name(generic_args: false) %}
1012

@@ -287,14 +289,33 @@ abstract struct Option(T)
287289
rescue
288290
None(T).new
289291
end
292+
293+
include Comparable(self)
294+
295+
def <=>(other : Option(T)) : Int32
296+
case {self, other}
297+
when {Some, None}
298+
1
299+
when {None, Some}
300+
-1
301+
when {None, None}
302+
0
303+
else
304+
{% if T.has_method?(:<=>) %}
305+
self.unwrap <=> other.unwrap
306+
{% else %}
307+
0
308+
{% end %}
309+
end
310+
end
290311
end
291312

292313
struct Some(T) < Option(T)
293314
@value : T
294315

295316
def initialize(value : T)
296317
{% if T.nilable? %}
297-
raise WrapingNil.new("typeof #{{{Some}}} cannot includes Nil")
318+
raise WrapingNil.new("typeof #{{{ Some }}} cannot includes Nil")
298319
{% end %}
299320

300321
@value = value
@@ -308,7 +329,7 @@ end
308329
struct None(T) < Option(T)
309330
def initialize
310331
{% if T.nilable? %}
311-
raise WrapingNil.new("typeof #{{{None}}} cannot includes Nil")
332+
raise WrapingNil.new("typeof #{{{ None }}} cannot includes Nil")
312333
{% end %}
313334
end
314335

src/result.cr

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ abstract struct Result(T, E)
55

66
class UnwrapErrOnOk < Exception; end
77

8+
class Uncomparable < Exception; end
9+
810
macro inherited
911
{% type = @type.name(generic_args: false) %}
1012

@@ -286,14 +288,35 @@ abstract struct Result(T, E)
286288
rescue
287289
Err(T, E).new(error)
288290
end
291+
292+
include Comparable(self)
293+
294+
def <=>(other : Result(T, E)) : Int32
295+
case {self, other}
296+
when {Ok, Err}
297+
-1
298+
when {Err, Ok}
299+
1
300+
else
301+
{% if T.has_method?(:<=>) && E.has_method?(:<=>) %}
302+
if self.is_a?(Ok)
303+
self.unwrap <=> other.unwrap
304+
else
305+
self.unwrap_err <=> other.unwrap_err
306+
end
307+
{% else %}
308+
0
309+
{% end %}
310+
end
311+
end
289312
end
290313

291314
struct Ok(T, E) < Result(T, E)
292315
@value : T
293316

294317
def initialize(value : T)
295318
{% if T.nilable? || E.nilable? %}
296-
raise WrapingNil.new("typeof #{{{Ok}}} cannot includes Nil")
319+
raise WrapingNil.new("typeof #{{{ Ok }}} cannot includes Nil")
297320
{% end %}
298321

299322
@value = value
@@ -309,7 +332,7 @@ struct Err(T, E) < Result(T, E)
309332

310333
def initialize(error : E)
311334
{% if T.nilable? || E.nilable? %}
312-
raise WrapingNil.new("typeof #{{{Err}}} cannot includes Nil")
335+
raise WrapingNil.new("typeof #{{{ Err }}} cannot includes Nil")
313336
{% end %}
314337

315338
@error = error

0 commit comments

Comments
 (0)