result

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 23, 2023 License: MIT Imports: 1 Imported by: 0

README

Go Reference

Functional Results

A Result type is similar to an Option but instead of Some and None, we need it to have Success and Failure where both have values associated with them.

Get it

go get -u github.com/flowonyx/functional/result

Use it

import "github.com/flowonyx/functional/result"

Types

Result[SuccessType, FailureType] is a generic type, where the types of the values associated with Success and Failure must be specified. This means that with a Failure, you can use error types or strings (or any other type you want).

Functions

  • IsSuccess tests if this Result has a value.
  • IsFailure tests if this Result has a failure.
  • IsSome is an alias for IsSuccess to satisfy the option.Optional interface.
  • IsNone is an alias for IsFailure to satisfy the option.Optional interface.
  • SuccessValue returns the value if this Result is Success. If the result is an error, Value returns the zero value of the value type.
  • FailureValue returns the error if this Result is Error. Otherwise, it returns nil.
  • Value is an alias for SuccessValue to satisfy the option.Optional interface.
  • Success creates a Result with a value.
  • Failure creates a Result with an error.
  • HandleResult accepts functions to handle a Result when it has a success or when it has an failure.
  • Bind applies a projection function from SuccessType->Result[AnyOtherType, _] when a Result is Success and otherwise returns the Failure.
  • Map applies a projection function from SuccessType->AnyOtherType when Result is Success and otherwise returns the Failure.
  • MapError applies mapping to the error when the Result is Failure and otherwise returns the Success.
  • DefaultValue returns the value of of a Result if it is Success. Otherwise, it returns the supplied default value.
  • DefaultWith returns the value of a Result if it is Success. Otherwise, it returns the output of a supplied function.
  • Contains tests whether the Result contains value.
  • Count returns 0 if this Result is Failure. Otherwise returns 1.
  • Exists tests whether the value of a Result matches a predicate function. If the Result is an error, it returns false.
  • Flatten returns the inner Result when Results are nested.
  • Fold applies a folder function to a Result with an initial state for the folder. If the Result is a Failure, the initial state is returned.
  • FoldBack applies the folder function to a Result with s being in the initial state for the folder. If the Result is a Failure, the initial state is returned.
  • ForAll tests whether the value contained in a Result matches a predicate function. It will always return true if the Result is a Failure.
  • Get returns the value of the Result. If Result is a Failure, it panics.
  • IsNone returns true if the Result is a Failure.
  • IsSome returns true if the Result is Success.
  • Iter applies an action function to the Result.
  • Map2 applies a function to two Results and returns the function's return value as a Result. If either Result is a Failure, it returns the error as the Result.
  • Map3 applies a function to three Results and returns the function's return value as a Result. If any of the Results is a Failure, it returns the error as the Result.
  • OfNullable creates a Result from a pointer.
    • If the pointer is nil, the Result will be a Failure with the the message "nil".
    • If the pointer is not nil, the Result will be Succeess of the value the pointer points to.
  • OrElse returns the given Result if it is a Success or the supplied value if it is a Failure.
  • OrElseWith returns the given Result if it is Success or the Result returned from a supplied function if it is a Failure.
  • ToSlice returns the value in Result as a single item slice.
  • If the Result is a Failure, it returns an empty slice.
  • ToNullable returns a pointer to the value in the Result if it is Success. If the Result is an Failure, it returns nil.
  • Lift adapts a function that returns a value and an error into a function that returns a Result that will be Success if there is no error and Failure if there is an error.
  • Lift1 adapts a function that accepts one input and returns a value and an error into a function that returns a Result that will be Success if there is no error and Failure if there is an error.
  • Lift2 adapts a function that accepts two inputs and returns a value and an error into a function that returns a Result that will be Success if there is no error and Failure if there is an error.

Documentation

Overview

Package result provides a helper type for error handling without returning multiple values. It also provides methodes for dealing with the Result type.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Contains

func Contains[S comparable, F any](value S, r Result[S, F]) bool

Contains tests whether the result contains value.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, string](1)
	input2 := result.Failure[int]("error")
	fmt.Println(result.Contains(1, input), result.Contains(1, input2))
}
Output:

true false

func Count

func Count[S, F any](r Result[S, F]) int

Count returns 0 if this result is Failure. Otherwise returns 1.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, string](1)
	input2 := result.Failure[int]("error")
	fmt.Println(result.Count(input), result.Count(input2))
}
Output:

1 0

func DefaultValue

func DefaultValue[S, F any](success S, r Result[S, F]) S

DefaultValue returns the value of r if r is Success. Otherwise, it returns success.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, error](1)
	input2 := result.Failure[int](fmt.Errorf("error"))
	r := result.DefaultValue(2, input)
	r2 := result.DefaultValue(2, input2)
	fmt.Println(r, r2)
}
Output:

1 2

func DefaultWith

func DefaultWith[S, F any](defThunk func() S, r Result[S, F]) S

DefaultWith returns the value of r if r is Success. Otherwise, it returns the output of defThunk.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, string](1)
	input2 := result.Failure[int]("error")
	r := result.DefaultWith(func() int { return 2 }, input)
	r2 := result.DefaultWith(func() int { return 2 }, input2)
	fmt.Println(r, r2)
}
Output:

1 2

func Exists

func Exists[S, F any](predicate func(S) bool, r Result[S, F]) bool

Exists tests whether the value of r matches the predicate. If the Result is an error, it returns false.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, string](1)
	input2 := result.Failure[int]("error")
	r := result.Exists(func(value int) bool { return value > 2 }, input)
	r2 := result.Exists(func(value int) bool { return value < 2 }, input)
	r3 := result.Exists(func(value int) bool { return value < 2 }, input2)
	fmt.Println(r, r2, r3)
}
Output:

false true false

func Fold

func Fold[S, F, State any](folder func(State, S) State, s State, r Result[S, F]) State

Fold applies the folder function to a Result with s being the initial state for the folder. If the Result is an Failure, the initial state is returned.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, string](5)
	r := result.Fold(func(state string, value int) string {
		return state + strconv.Itoa(value)
	}, "state:", input)
	fmt.Println(r)
}
Output:

state:5

func FoldBack

func FoldBack[S, F, State any](folder func(S, State) State, r Result[S, F], s State) State

FoldBack applies the folder function to a Result with s being in the initial state for the folder. If the Result is an Failure, the initial state is returned.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, string](5)
	r := result.FoldBack(func(value int, state string) string {
		return state + strconv.Itoa(value)
	}, input, "state:")
	fmt.Println(r)
}
Output:

state:5

func ForAll

func ForAll[S, F any](predicate func(S) bool, r Result[S, F]) bool

ForAll tests whether the value contained in the Result matches the predicate. It will always return true if the Result is a Failure.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input1 := result.Success[int, string](1)
	input2 := result.Failure[int]("error")
	r1 := result.ForAll(func(v int) bool { return v < 2 }, input1)
	r2 := result.ForAll(func(v int) bool { return v > 2 }, input1)
	r3 := result.ForAll(func(v int) bool { return v < 2 }, input2)
	fmt.Println(r1, r2, r3)
}
Output:

true false true

func Get

func Get[S, F any](r Result[S, F]) S

Get returns the value of the Result. If Result is a Failure, it panics.

func HandleResult

func HandleResult[S, F, R any](r Result[S, F], whenSuccess func(S) R, whenFailure func(F) R) R

HandleResult accepts functions to handle a Result when it has a success or when it has an failure. This will panic if either of the functions are nil.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	res := result.Success[int, error](1)
	err := result.HandleResult(res, func(i int) error {
		fmt.Println(i)
		return nil
	}, func(err error) error {
		fmt.Println(err)
		return err
	})
	if err != nil {
		panic(err)
	}
}
Output:

1

func IsNone

func IsNone[S, F any](r Result[S, F]) bool

IsNone returns true if the Result is a Failure.

func IsSome

func IsSome[S, F any](r Result[S, F]) bool

IsSome returns true if the Result is Success.

func Iter

func Iter[S, F any](action func(S), r Result[S, F])

Iter applies the action to the result.

func Lift

func Lift[S, F any](f func() (S, error)) func() Result[S, F]

Lift adapts a function that returns a value and an error into a function that returns a Result that will be Success if there is no error and Failure if there is an error.

func Lift1

func Lift1[T, S, F any](f func(T) (S, error)) func(T) Result[S, F]

Lift1 adapts a function that accepts one input and returns a value and an error into a function that returns a Result that will be Success if there is no error and Failure if there is an error.

func Lift2

func Lift2[T1, T2, S, F any](f func(T1, T2) (S, error)) func(T1, T2) Result[S, F]

Lift2 adapts a function that accepts two inputs and returns a value and an error into a function that returns a Result that will be Success if there is no error and Failure if there is an error.

func ToNullable

func ToNullable[S, F any](r Result[S, F]) *S

ToNullable returns a pointer to the value in the Result if it is Success. If the Result is an Failure, it returns nil.

func ToSlice

func ToSlice[S, F any](r Result[S, F]) []S

ToSlice returns the value in Result as a single item slice. If the Result is an Failure, it returns an empty slice.

Types

type Result

type Result[S, F any] struct {
	// contains filtered or unexported fields
}

Result is a helper type for error handling without returning multiple values. Any Result will either contain a value or an error.

func Bind

func Bind[S, F, R any](binder func(S) Result[R, F], r Result[S, F]) Result[R, F]

Bind applies binder when result is Success and otherwise returns the Failure.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, error](2)
	res := result.Bind(func(t int) result.Result[int, error] { return result.Success[int, error](t * 2) }, input)
	if res.IsFailure() {
		panic(res.FailureValue())
	}
	if !res.IsSuccess() {
		panic("not ok")
	}
	fmt.Println(res.SuccessValue())
}
Output:

4
Example (Second)
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, error](2)
	res := result.Bind(func(t int) result.Result[int, error] { return result.Failure[int](fmt.Errorf("error: %d", t)) }, input)
	res = result.Bind(func(t int) result.Result[int, error] { return result.Success[int, error](t) }, res)
	if res.IsSuccess() {
		panic("should not be ok")
	}
	if !res.IsFailure() {
		panic("should be error")
	}
	fmt.Println(res.FailureValue())
}
Output:

error: 2

func Failure

func Failure[S, F any](v F) Result[S, F]

Failure creates a Result with an error.

func Flatten

func Flatten[S, F any](rr Result[Result[S, F], F]) Result[S, F]

Flatten returns the inner Result when Results are nested.

func Map

func Map[S, F, R any](mapping func(S) R, r Result[S, F]) Result[R, F]

Map applies mapping when result is Success and otherwise returns the Failure.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	input := result.Success[int, string](1)
	res := result.Map(func(i int) string { return fmt.Sprint("input: ", i) }, input)
	fmt.Println(res.SuccessValue())
}
Output:

input: 1

func Map2

func Map2[S1, S2, F, R any](f func(S1, S2) R, r1 Result[S1, F], r2 Result[S2, F]) Result[R, F]

Map2 applies function f to two Results and returns the function's return value as a Result. If either Result is an Error, it returns the error as the Result.

func Map3

func Map3[S1, S2, S3, F, R any](f func(S1, S2, S3) R, r1 Result[S1, F], r2 Result[S2, F], r3 Result[S3, F]) Result[R, F]

Map3 applies function f to three Results and returns the function's return value as a Result. If any of the Results is an Error, it returns the error as the Result.

func MapError

func MapError[S, F any](mapping func(F) F, r Result[S, F]) Result[S, F]

MapError applies mapping to the error when the result is Failure and otherwise returns the Success.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/result"
)

func main() {
	mapping := func(err error) error {
		return fmt.Errorf("%w: wrapped", err)
	}
	input := result.Success[int, error](1)
	input2 := result.Failure[int](fmt.Errorf("inner error"))
	res := result.MapError(mapping, input)
	res2 := result.MapError(mapping, input2)
	fmt.Println(res.String(), res2.String())
}
Output:

1 inner error: wrapped

func OfNullable

func OfNullable[S, F any](value *S) Result[S, F]

OfNullable creates a result from a pointer. If the pointer is nil, the result will be a Failure with the the message "nil". If the pointer is not nil, the result will be Succeess of the value the pointer points to.

func OrElse

func OrElse[S, F any](ifNone Result[S, F], r Result[S, F]) Result[S, F]

OrElse returns r if it is Success or ifNone if r is a Failure.

func OrElseWith

func OrElseWith[S, F any](ifNoneThunk func() Result[S, F], r Result[S, F]) Result[S, F]

OrElseWith returns r if it is Success or the Result returned from ifNoneThunk if r is an Error.

func Success

func Success[S, F any](v S) Result[S, F]

Success creates a Result with a value.

func (Result[_, F]) FailureValue

func (r Result[_, F]) FailureValue() F

FailureValue returns the error if this Result is Error. Otherwise, it returns nil.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/flowonyx/functional/result"
)

func main() {
	r := result.Failure[int]("bad argument")
	r2 := result.Success[int, error](1)
	fmt.Println(strconv.Quote(r.FailureValue()), r2.FailureValue())
}
Output:

"bad argument" <nil>

func (Result[_, _]) IsFailure

func (r Result[_, _]) IsFailure() bool

IsFailure tests if this Result has a failure.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/errors"
	"github.com/flowonyx/functional/result"
)

func main() {
	r := result.Success[int, error](1)
	r2 := result.Failure[int](errors.BadArgumentErr)
	fmt.Println(r.IsFailure(), r2.IsFailure())
}
Output:

false true

func (Result[_, _]) IsNone

func (r Result[_, _]) IsNone() bool

IsNone is an alias for IsFailure to satisfy the option.Optional interface.

func (Result[_, _]) IsSome

func (r Result[_, _]) IsSome() bool

IsSome is an alias for IsSuccess to satisfy the option.Optional interface.

func (Result[_, _]) IsSuccess

func (r Result[_, _]) IsSuccess() bool

IsSuccess tests if this Result has a value.

Example
package main

import (
	"fmt"

	"github.com/flowonyx/functional/errors"
	"github.com/flowonyx/functional/result"
)

func main() {
	r := result.Success[int, error](1)
	r2 := result.Failure[int](errors.BadArgumentErr)
	fmt.Println(r.IsSuccess(), r2.IsSuccess())
}
Output:

true false

func (*Result[_, _]) String

func (r *Result[_, _]) String() string

func (Result[S, _]) SuccessValue

func (r Result[S, _]) SuccessValue() S

SuccessValue returns the value if this Result is Success. If the result is an error, Value returns the zero value of the value type.

func (Result[S, _]) Value

func (r Result[S, _]) Value() S

Value is an alias for SuccessValue to satisfy the option.Optional interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL