salvation

package module
v0.6.91 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2025 License: Unlicense Imports: 3 Imported by: 0

README

🌀 Salvation

salvation is a package containing a generic Go wrapper for optional values.

Inspired by Rust's Option<T> and Haskell's Maybe, Possibly[T] gives you a way to wrap things that may or may not exist, and then reflect on their Nothingness.

✨ Features

  • Generic support for any type T
  • Reflection-powered nil checking
  • Precomputable "Nothingness" for less overhead
  • Configurable rules (empty slices can be something... if you believe)
  • Matcher flow control
  • Fully documented (yes, this is a feature)

🧠 Why?

Honestly? I don't know. But it seemed fun enough to build.

🚀 Usage

Usage examples below. A full Wiki is coming soon (probably just so I can pretend it matters).

opt := salvation.NewPossibility[*MyStruct](nil)

if opt.IsSomething() {
    // yay!
}

if opt.IsNothing() {
    // aww!
}
opt.Match().
    Case(func(v int) bool { return v > 10 }, func(v int) { fmt.Println("Large number", v) }).
    Default(func(_ Possibly[int]) {
        fmt.Println("Nothing matched. Or maybe there was Nothing at all.")
    })

🫠 Contributing

Thinking of contributing? That's adorable.

Before submitting a PR, feature request, or unhinged philosophical improvement, please consult the CONTRIBUTING.md. It's full of helpful guidelines, emotional red flags, and vague threats.

If you're still interested after reading it, I can't stop you. No one can.

⭐️ Validation

If this repo made you feel something (anything at all) you can click the star. It won't fix your life, but it'll make this repo slightly more visible to other souls.

I made this section against my own will...

🧯 License

This project uses The Unlicense license (just copy and paste into your code and believe in yourself)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Matcher

type Matcher[T any] struct {
	// contains filtered or unexported fields
}

Matcher is a control-flow utility for Possibly[T] values, enabling chained case handling. It mimics pattern matching from languages like Rust and Kotlin but does so in an aggressively Go-inappropriate way, allowing you to define match-like behavior for conditional logic.

Matcher will execute the first matching case unless MatchAllCases is set to true, in which case it evaluates all matching cases.

func (Matcher[T]) Case

func (m Matcher[T]) Case(predicate func(T) bool, action func(T)) Matcher[T]

Case tests a predicate against the Possibly's value. If the predicate returns true, the corresponding action is executed.

If MatchAllCases is false, only the first matching Case is executed. If the Possibly is Nothing, Case is skipped silently, as if it never existed.

func (Matcher[T]) Default

func (m Matcher[T]) Default(action func(Possibly[T]))

Default provides a fallback action to run if no Case matched. It receives the original Possibly[T] value, allowing inspection or logging.

type MatcherConfig

type MatcherConfig struct {
	// MatchAllCases, when true, allows all Case predicates to be evaluated.
	// If false (default), only the first matching Case is executed.
	MatchAllCases bool
}

MatcherConfig controls evaluation strategy for Matcher.

type Possibly

type Possibly[T any] struct {
	// contains filtered or unexported fields
}

Possibly is a generic wrapper that represents an optional value of type T. It mimics constructs like Rust's Option<T> or Haskell's Maybe, allowing for safe handling or potentially nil or invalid values.

Possibly tracks whether a value is effectively "Nothing" (nil) using reflection for Go types that support nil (pointers, slices, maps, etc).

func NewPossibility

func NewPossibility[T any](value T) Possibly[T]

NewPossibility wraps a value of type T and returns an Possibly[T].

Example:

opt := NewPossibility[*MyStruct](nil)
if opt.IsNothing() { ... }

func NewPossibilityWithConfig

func NewPossibilityWithConfig[T any](value T, opts PossiblyConfig) Possibly[T]

NewPossibilityWithConfig wraps a value of type T and returns an Possibly[T]. It uses the configuration to affect the behaviour of Possibly[T] (i.e., caching, design rules).

Example:

opt := NewPossibilityWithConfig[*MyStruct](nil, &PossiblyConfig{Precompute: true})
if opt.IsNothing() { ... }

func (Possibly[T]) IsNothing

func (p Possibly[T]) IsNothing() bool

IsNothing returns true if the Possibly contains a nil or invalid value. For nilable types (pointers, slices, interfaces, etc), it checks if the internal value is nil. For non-nilable types, it always returns false.

func (Possibly[T]) IsPrecomputed

func (p Possibly[T]) IsPrecomputed() bool

IsPrecomputed returns true if Possibly[T] is using a cached "Nothing" value.

func (Possibly[T]) IsSomething

func (p Possibly[T]) IsSomething() bool

IsSomething returns true if the Possibly contains a non-nil, valid value.

Note: For non-nilable types (like int, struct), IsSomething always returns true.

func (Possibly[T]) Match

func (p Possibly[T]) Match() Matcher[T]

Match creates a Matcher from a Possibly[T] value. Use it to build a fluent-style series of Case and Default handlers.

func (Possibly[T]) MatchWithConfig

func (p Possibly[T]) MatchWithConfig(opts MatcherConfig) Matcher[T]

MatchWithConfig creates a Matcher with explicit configuration options.

func (Possibly[T]) MustReveal

func (p Possibly[T]) MustReveal() T

MustReveal returns the underlying value if it exists. It panics if the Possibly is Nothing.

func (Possibly[T]) Reveal

func (p Possibly[T]) Reveal() (T, bool)

Reveal returns the value and a bool indicating presence.

func (Possibly[T]) RevealOrElse

func (p Possibly[T]) RevealOrElse(value T) T

RevealOrElse returns the underlying value if it's present, or the fallback value otherwise.

func (Possibly[T]) SafeReveal

func (p Possibly[T]) SafeReveal() (*T, error)

SafeReveal returns the underlying value as a pointer if it exists, or returns an error if the Possibly is Nothing.

func (Possibly[T]) String

func (p Possibly[T]) String() string

String returns a string representation of the Possibly[T]. If the value is considered "Nothing", it returns "<Nothing>". Otherwise, it returns "<Something: VALUE>", using fmt.Sprintf on the underlying value.

This method is useful for debugging and logging.

func (*Possibly[T]) TryRecomputeIsNothing

func (p *Possibly[T]) TryRecomputeIsNothing() error

TryRecomputeIsNothing forcibly updates the cached nil status, if precomputation is enabled. Returns an error if precomputation is disabled.

type PossiblyConfig

type PossiblyConfig struct {
	// Precompute enables caching of the "Nothingness" state at construction time.
	// When true, Possibly[T] will evaluate and store the result of IsNothing()
	// at creation time, avoiding reflection during future calls.
	//
	// Note: If the original value changes after creation (e.g., pointer set to nil),
	// the cached result may become stale. Only enable this if the wrapped value is immutable.
	// You can still force a recache using TryRecomputeIsNothing() method.
	Precompute bool

	// TreatZeroSliceAsSomething determines whether empty slices should be treated
	// as valid ("Something") rather than nil-equivalent ("Nothing").
	//
	// When true, an empty slice (e.g., var s []T) will *not* be considered "Nothing".
	// When false, empty slices behave like nil slices and are considered "Nothing".
	//
	// This only affects types of kind reflect.Slice.
	TreatZeroSliceAsSomething bool
}

PossiblyConfig defines configuration options that affect how Possibly[T] determines whether a value is considered "Nothing" (i.e., nil).

Jump to

Keyboard shortcuts

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