Skip to content

Commit dfea9eb

Browse files
committed
add: MayAt, TryAt and MustAt constructor for safe access slice
1 parent 4f8106f commit dfea9eb

4 files changed

Lines changed: 66 additions & 0 deletions

File tree

option_make.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ func MayLookUp[K comparable, T any](m map[K]T, key K) Option[T] {
3838
return Some(val)
3939
}
4040

41+
// MayAt attempts to retrieve an element from a slice by index, returning an Option.
42+
// Arrays can be passed as arr[:].
43+
func MayAt[T any](x []T, index int) Option[T] {
44+
if index < 0 || index >= len(x) {
45+
return None[T]()
46+
}
47+
return Some(x[index])
48+
}
49+
4150
// MaybeEmpty builds a Some Option when val is not empty, or None.
4251
func MaybeEmpty[T any](val T) Option[T] {
4352
if IsEmpty(val) {

option_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ func TestFromMayHave(t *testing.T) {
3232
is.Equal(Option[int]{hasVal: true, val: 42}, MayHave(cb(42, true)()))
3333
}
3434

35+
func TestFromMayAt(t *testing.T) {
36+
is := assert.New(t)
37+
38+
slice := []int{10, 20, 30}
39+
array := [3]int{40, 50, 60}
40+
41+
is.Equal(Option[int]{hasVal: true, val: 20}, MayAt(slice, 1))
42+
is.Equal(Option[int]{hasVal: true, val: 60}, MayAt(array[:], 2))
43+
is.Equal(Option[int]{hasVal: false}, MayAt(slice, -1))
44+
is.Equal(Option[int]{hasVal: false}, MayAt(slice, 3))
45+
is.Equal(Option[int]{hasVal: false}, MayAt([]int{}, 0))
46+
}
47+
3548
func TestOptionMaybeCast(t *testing.T) {
3649
is := assert.New(t)
3750

result_make.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ func TryLookUp[K comparable, T any](m map[K]T, key K) Result[T] {
3737
return Ok(val)
3838
}
3939

40+
// TryAt attempts to retrieve an element from a slice by index, returning a Result.
41+
// Arrays can be passed as arr[:].
42+
func TryAt[T any](x []T, index int) Result[T] {
43+
if index < 0 || index >= len(x) {
44+
return Err[T](fmt.Errorf("%w: index %d out of bounds", ErrNoSuchElement, index))
45+
}
46+
return Ok(x[index])
47+
}
48+
4049
// TryIf constructs a Result with no value from just a boolean flag.
4150
func TryIf(ok bool) Result[Unit] {
4251
if !ok {
@@ -80,6 +89,12 @@ func MustLookUp[K comparable, T any](m map[K]T, key K) T {
8089
return TryLookUp(m, key).Yield()
8190
}
8291

92+
// MustAt retrieves an element from a slice by index, bails out if the index is out of bounds.
93+
// Arrays can be passed as arr[:].
94+
func MustAt[T any](x []T, index int) T {
95+
return TryAt(x, index).Yield()
96+
}
97+
8398
// MustTrue bails out if the boolean flag is false.
8499
func MustTrue(ok bool) {
85100
TryIf(ok).Yield()

result_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ func TestResultTryIf(t *testing.T) {
4242
is.Equal(Try(3, fmt.Errorf("%w: %T", ErrNoSuchElement, 3)), TryHave(3, false))
4343
}
4444

45+
func TestResultTryAt(t *testing.T) {
46+
is := assert.New(t)
47+
48+
slice := []int{10, 20, 30}
49+
array := [3]int{40, 50, 60}
50+
51+
is.Equal(Ok(20), TryAt(slice, 1))
52+
is.Equal(Ok(60), TryAt(array[:], 2))
53+
is.ErrorIs(TryAt(slice, -1).Err(), ErrNoSuchElement)
54+
is.ErrorIs(TryAt(slice, 3).Err(), ErrNoSuchElement)
55+
is.ErrorIs(TryAt([]int{}, 0).Err(), ErrNoSuchElement)
56+
}
57+
4558
func TestResultTryCast(t *testing.T) {
4659
is := assert.New(t)
4760

@@ -95,6 +108,22 @@ func TestResultMustOk(t *testing.T) {
95108
is.Equal(42, Ok(42).Yield())
96109
}
97110

111+
func TestResultMustAt(t *testing.T) {
112+
is := assert.New(t)
113+
114+
slice := []int{10, 20, 30}
115+
array := [3]int{40, 50, 60}
116+
117+
is.Equal(20, MustAt(slice, 1))
118+
is.Equal(60, MustAt(array[:], 2))
119+
is.Panics(func() {
120+
MustAt(slice, -1)
121+
})
122+
is.Panics(func() {
123+
MustAt(slice, 3)
124+
})
125+
}
126+
98127
func TestResultOr(t *testing.T) {
99128
is := assert.New(t)
100129

0 commit comments

Comments
 (0)