spans

package module
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: May 27, 2025 License: MIT Imports: 4 Imported by: 0

README

spans GoDoc Go Report Card

A minimal, Python-like span/range utility for integers in Go.

The spans package provides an efficient and allocation-free way to represent ranges of integers. It supports slicing, indexing, containment, and iteration in O(1) time where possible, and is especially useful for Unicode filtering, numeric range matching, and logic replacement for manual loops.


✨ Features

  • ✅ Define spans with start, stop, and step
  • ✅ Allocation-free representation
  • ✅ Constant-time: Len, Contains, At, Find
  • ✅ Interoperable with iter.Seq
  • ❌ Immutable (no dynamic insertion/removal)
  • ❌ Integer-only (no float/string ranges)

🧱 Example

package main

import (
	"fmt"
	"github.com/byExist/spans"
)

func main() {
	hangul := spans.Range(0xAC00, 0xD7A3 + 1)

	ch := '강'
	fmt.Printf("'%c' (%U) is Hangul? %v\n", ch, ch, spans.Contains(hangul, int(ch)))

	ch = 'A'
	fmt.Printf("'%c' (%U) is Hangul? %v\n", ch, ch, spans.Contains(hangul, int(ch)))
}
// Using Stride to generate even numbers from 0 to 10
evens := spans.Stride(0, 10, 2)
for _, v := range spans.Values(evens) {
    fmt.Println(v)
}

📚 Use When

  • You need efficient range checking or indexing
  • You want a zero-allocation alternative to slices
  • You work with Unicode, event codes, or numeric classes

🚫 Avoid If

  • You need dynamic range mutation
  • You want to hold non-integer values
  • You need interval trees or overlapping span logic

📊 Performance

Benchmarked on Apple M1 Pro (darwin/arm64):

Operation Time (ns/op) Allocations
Contains 2.13 0
Len 2.12 0
At 2.23 0
Find 2.52 0

🔍 API

Function Description
To(stop) span from 0 to stop
Range(start, stop) span from start to stop
Stride(start, stop, step) span from start to stop with step
Len(span) number of elements
Contains(span, elem) test for membership
At(span, index) value at index
Find(span, value) index of value
Values(span) iterator over span

⚠️ Limitations

  • step must not be 0 (will panic)
  • start, stop, and step must define a finite sequence

🪪 License

MIT License. See LICENSE.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func At

func At(s Span, index int) (int, bool)

At returns the element at the given index in the span. Returns false if the index is out of bounds.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(10, 20, 2)
	v, ok := spans.At(s, 2)
	fmt.Println(v)
	fmt.Println(ok)
	_, ok = spans.At(s, 10)
	fmt.Println(ok)
}
Output:

14
true
false

func Contains

func Contains(s Span, elem int) bool

Contains returns true if the given element is contained within the span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(0, 6, 2)
	fmt.Println(spans.Contains(s, 4))
	fmt.Println(spans.Contains(s, 5))
}
Output:

true
false

func Find

func Find(s Span, elem int) (int, bool)

Find returns the index of the element in the span. Returns false if the element is not in the span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(0, 10, 2)
	i, ok := spans.Find(s, 6)
	fmt.Println(i)
	fmt.Println(ok)
	_, ok = spans.Find(s, 5)
	fmt.Println(ok)
}
Output:

3
true
false

func Len

func Len(s Span) int

Len returns the number of elements in the span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	fmt.Println(spans.Len(spans.Stride(0, 5, 2)))
	fmt.Println(spans.Len(spans.Stride(5, 0, -2)))
}
Output:

3
3

func Values

func Values(s Span) iter.Seq[int]

Values returns an iterator that yields values in the span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(1, 6, 2)
	for v := range spans.Values(s) {
		fmt.Print(v, " ")
	}
}
Output:

1 3 5

Types

type Span

type Span struct {
	// contains filtered or unexported fields
}

Span represents a range of integers with a start, stop, and step.

func Clone added in v0.1.0

func Clone(s Span) Span

Clone creates a copy of the given Span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(1, 5, 1)
	cloned := spans.Clone(s)
	for v := range spans.Values(cloned) {
		fmt.Print(v, " ")
	}
}
Output:

1 2 3 4

func Range

func Range(start, stop int) Span

Range returns a Span starting at the given start and ending before stop, with a step of 1.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Range(1, 4)
	for v := range spans.Values(s) {
		fmt.Print(v, " ")
	}
}
Output:

1 2 3

func Stride

func Stride(start, stop, step int) Span

Stride returns a Span with the specified start, stop, and step values. Panics if the step is 0.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(0, 6, 2)
	for v := range spans.Values(s) {
		fmt.Print(v, " ")
	}
}
Output:

0 2 4

func To

func To(stop int) Span

To returns a Span starting at 0 and ending before the given stop value, with a step of 1.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.To(3)
	for v := range spans.Values(s) {
		fmt.Print(v, " ")
	}
}
Output:

0 1 2

func (Span) MarshalJSON added in v0.3.0

func (s Span) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(0, 6, 2)
	data, _ := json.Marshal(s)
	fmt.Println(string(data))
}
Output:

[0,6,2]

func (Span) Start

func (i Span) Start() int

Start returns the starting value of the span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	fmt.Println(spans.Stride(3, 10, 2).Start())
}
Output:

3

func (Span) Step

func (i Span) Step() int

Step returns the step size of the span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	fmt.Println(spans.Stride(3, 10, 2).Step())
}
Output:

2

func (Span) Stop

func (i Span) Stop() int

Stop returns the stopping value of the span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	fmt.Println(spans.Stride(3, 10, 2).Stop())
}
Output:

10

func (Span) String added in v0.3.0

func (s Span) String() string

String returns a string representation of the Span.

Example
package main

import (
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	s := spans.Stride(2, 8, 2)
	fmt.Println(s.String())
}
Output:

Span(2, 8, 2)

func (*Span) UnmarshalJSON added in v0.3.0

func (s *Span) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/byExist/spans"
)

func main() {
	var s spans.Span
	_ = json.Unmarshal([]byte(`[1,5,1]`), &s)
	fmt.Println(s.String())
}
Output:

Span(1, 5, 1)

Jump to

Keyboard shortcuts

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