Skip to content

Commit 112514d

Browse files
committed
feat: add missing methods, add sig
1 parent e018a93 commit 112514d

7 files changed

Lines changed: 569 additions & 9 deletions

File tree

Rakefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ RuboCop::RakeTask.new do |task|
1010
task.plugins << "rubocop-rspec"
1111
end
1212

13-
task default: [:spec, :rubocop]
13+
task default: [:spec]

lib/rs/option.rb

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,111 @@ def unwrap_or(default)
4848
def unwrap_or_else(&block)
4949
is_some ? @value : block.call
5050
end
51+
52+
def map(type, &block)
53+
if is_some
54+
Some[type] { block.call(@value) }
55+
else
56+
None[type]
57+
end
58+
end
59+
60+
def map_or(default, &block)
61+
is_some ? block.call(@value) : default
62+
end
63+
64+
def map_or_else(default, &block)
65+
is_some ? block.call(@value) : default.call
66+
end
67+
68+
def ok_or(error)
69+
if is_some
70+
Ok[@type, error.class] { @value }
71+
else
72+
Err[@type, error.class] { error }
73+
end
74+
end
75+
76+
def ok_or_else(&block)
77+
error = block.call
78+
if is_some
79+
Ok[@type, error.class] { @value }
80+
else
81+
Err[@type, error.class] { error }
82+
end
83+
end
84+
85+
def and(other)
86+
if is_some
87+
other
88+
else
89+
other.is_some ? None[other.unwrap.class] : None[other.type]
90+
end
91+
end
92+
93+
def and_then(type, &block)
94+
is_some ? block.call(@value) : None[type]
95+
end
96+
97+
def select(&block)
98+
if is_some
99+
block.call(@value) ? self : None[@type]
100+
else
101+
None[@type]
102+
end
103+
end
104+
105+
def or(other)
106+
if is_some
107+
self
108+
else
109+
other
110+
end
111+
end
112+
113+
def or_else(&block)
114+
is_some ? self : block.call
115+
end
116+
117+
def xor(other)
118+
case [is_some, other.is_some]
119+
when [true, false]
120+
self
121+
when [false, true]
122+
other
123+
when [true, true]
124+
None[@type]
125+
else
126+
None[@type]
127+
end
128+
end
129+
130+
def tap(&block)
131+
if is_some
132+
value = @value
133+
block.call(value)
134+
end
135+
self
136+
end
137+
138+
def self.from(type, &block)
139+
Some[type, &block]
140+
end
141+
142+
def self.from?(type, &block)
143+
value = block.call
144+
if value == nil
145+
None[type]
146+
else
147+
Some[type] { value }
148+
end
149+
end
150+
151+
def self.from!(type, &block)
152+
Some[type, &block]
153+
rescue StandardError
154+
None[type]
155+
end
51156
end
52157
end
53158

lib/rs/result.rb

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,98 @@ def expect_err(msg)
6666
def unwrap_err
6767
is_ok ? raise(UnwrapErrOnOk.new("called unwrap_err() on an Ok value: #{@value}")) : @error
6868
end
69+
70+
def map(value_type, &block)
71+
if is_ok
72+
Ok[value_type, @error_type] { block.call(@value) }
73+
else
74+
Err[value_type, @error_type] { @error }
75+
end
76+
end
77+
78+
def map_or(default, &block)
79+
is_ok ? block.call(@value) : default
80+
end
81+
82+
def map_or_else(default, &block)
83+
is_ok ? block.call(@value) : default.call(@error)
84+
end
85+
86+
def map_err(error_type, &block)
87+
if is_ok
88+
Ok[@value_type, error_type] { @value }
89+
else
90+
Err[@value_type, error_type] { block.call(@error) }
91+
end
92+
end
93+
94+
def tap(&block)
95+
if is_ok
96+
value = @value
97+
block.call(value)
98+
end
99+
self
100+
end
101+
102+
def inspect_err(&block)
103+
if is_err
104+
error = @error
105+
block.call(error)
106+
end
107+
self
108+
end
109+
110+
def and(other)
111+
if is_ok
112+
other
113+
else
114+
Err[other.value_type, @error_type] { @error }
115+
end
116+
end
117+
118+
def and_then(value_type, &block)
119+
if is_ok
120+
block.call(@value)
121+
else
122+
Err[value_type, @error_type] { @error }
123+
end
124+
end
125+
126+
def or(other)
127+
if is_ok
128+
Ok[@value_type, other.error_type] { @value }
129+
else
130+
other
131+
end
132+
end
133+
134+
def or_else(error_type, &block)
135+
if is_ok
136+
Ok[@value_type, error_type] { @value }
137+
else
138+
block.call(@error)
139+
end
140+
end
141+
142+
def self.from_or(value_type, error, &block)
143+
Ok[value_type, error.class] { block.call }
144+
end
145+
146+
def self.from_or?(value_type, error, &block)
147+
value = block.call
148+
if value == nil
149+
Err[value_type, error.class] { error }
150+
else
151+
Ok[value_type, error.class] { value }
152+
end
153+
end
154+
155+
def self.from_or!(value_type, error, &block)
156+
value = block.call
157+
Ok[value_type, error.class] { value }
158+
rescue StandardError
159+
Err[value_type, error.class] { error }
160+
end
69161
end
70162
end
71163

sig/rs/option.rbs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
module Rs
2+
class Option
3+
class TypeError < StandardError
4+
def initialize: (type untyped) -> void
5+
end
6+
7+
class TypeNilClass < StandardError; end
8+
class TypeMismatch < StandardError; end
9+
class WrapNil < StandardError; end
10+
class UnwrapNone < StandardError; end
11+
12+
def is_some: () -> bool
13+
def is_some_and: () { (T) -> bool } -> bool
14+
def is_none: () -> bool
15+
def is_none_or: () { (T) -> bool } -> bool
16+
def expect: (String) -> T
17+
def unwrap: () -> T
18+
def unwrap_or: (T) -> T
19+
def unwrap_or_else: () { () -> T } -> T
20+
def map: (Class type) { (T) -> U } -> Option[U]
21+
def map_or: (U) { (T) -> U } -> U
22+
def map_or_else: (Proc) { (T) -> U } -> U
23+
def ok_or: (E) -> Result[T, E]
24+
def ok_or_else: () { () -> E } -> Result[T, E]
25+
def and: (Option[U]) -> Option[U]
26+
def and_then: (Class type) { (T) -> Option[U] } -> Option[U]
27+
def select: () { (T) -> bool } -> Option[T]
28+
def or: (Option[T]) -> Option[T]
29+
def or_else: () { () -> Option[T] } -> Option[T]
30+
def xor: (Option[T]) -> Option[T]
31+
def tap: () { (T) -> void } -> Option[T]
32+
def self.from: (Class type) { () -> T } -> Option[T]
33+
def self.from?: (Class type) { () -> T | nil } -> Option[T]
34+
def self.from!: (Class type) { () -> T } -> Option[T]
35+
end
36+
37+
class Some < Option
38+
attr_reader type: Class
39+
attr_reader value: T
40+
41+
def self.[]: (Class type) { () -> T } -> Some[T]
42+
def initialize: (T value) -> void
43+
def inspect: () -> String
44+
def ==: (untyped) -> bool
45+
end
46+
47+
class None < Option
48+
attr_reader type: Class
49+
50+
def self.[]: (Class type) -> None[T]
51+
def initialize: (Class type) -> void
52+
def inspect: () -> String
53+
def ==: (untyped) -> bool
54+
end
55+
end

sig/rs/result.rbs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,65 @@
11
module Rs
2+
class Result
3+
class TypeError < StandardError
4+
def initialize: (untyped value_type, untyped error_type) -> void
5+
end
6+
7+
class TypeNilClass < StandardError; end
8+
class TypeMismatch < StandardError; end
9+
class WrapNil < StandardError; end
10+
class UnwrapOnErr < StandardError; end
11+
class UnwrapErrOnOk < StandardError; end
12+
13+
def is_ok: () -> bool
14+
def is_ok_and: () { (T) -> bool } -> bool
15+
def is_err: () -> bool
16+
def is_err_and: () { (E) -> bool } -> bool
17+
def ok: () -> Option[T]
18+
def err: () -> Option[E]
19+
def expect: (String) -> T
20+
def unwrap: () -> T
21+
def unwrap_or: (T) -> T
22+
def unwrap_or_else: () { (E) -> T } -> T
23+
def expect_err: (String) -> E
24+
def unwrap_err: () -> E
25+
def map: (Class value_type) { (T) -> U } -> Result[U, E]
26+
def map_or: (U) { (T) -> U } -> U
27+
def map_or_else: (Proc) { (T) -> U } -> U
28+
def map_err: (Class error_type) { (E) -> F } -> Result[T, F]
29+
def tap: () { (T) -> void } -> Result[T, E]
30+
def inspect_err: () { (E) -> void } -> Result[T, E]
31+
def and: (Result[U, E]) -> Result[U, E]
32+
def and_then: (Class value_type) { (T) -> Result[U, E] } -> Result[U, E]
33+
def or: (Result[T, F]) -> Result[T, F]
34+
def or_else: (Class error_type) { (E) -> Result[T, F] } -> Result[T, F]
35+
def self.from_or: (Class value_type, E error) { () -> T } -> Result[T, E]
36+
def self.from_or?: (Class value_type, E error) { () -> T | nil } -> Result[T, E]
37+
def self.from_or!: (Class value_type, E error) { () -> T } -> Result[T, E]
38+
end
39+
40+
class Ok < Result
41+
attr_reader value: T
42+
attr_reader value_type: Class
43+
attr_accessor error_type: Class
44+
45+
def self.[]: (Class value_type, Class error_type) { () -> T } -> Ok[T, E]
46+
def initialize: (T value) -> void
47+
def inspect: () -> String
48+
def ==: (untyped) -> bool
49+
end
50+
51+
class Err < Result
52+
attr_reader error: E
53+
attr_reader error_type: Class
54+
attr_accessor value_type: Class
55+
56+
def self.[]: (Class value_type, Class error_type) { () -> E } -> Err[T, E]
57+
def initialize: (E error) -> void
58+
def inspect: () -> String
59+
def ==: (untyped) -> bool
60+
end
61+
262
module Result
363
VERSION: String
4-
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
564
end
665
end

0 commit comments

Comments
 (0)