Style/rename internal rand (#701)

* style: rename internal/rand package to internal/xrand

* doc: internal package readme

* oops
This commit is contained in:
Samuel Berthe
2025-10-05 00:42:41 +02:00
committed by GitHub
parent 380e1a0ae2
commit 18c5a43f79
9 changed files with 27 additions and 23 deletions
+3 -3
View File
@@ -5,7 +5,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/samber/lo/internal/rand" "github.com/samber/lo/internal/xrand"
) )
// DispatchingStrategy is a function that distributes messages to channels. // DispatchingStrategy is a function that distributes messages to channels.
@@ -92,7 +92,7 @@ func DispatchingStrategyRoundRobin[T any](msg T, index uint64, channels []<-chan
// Play: https://go.dev/play/p/GEyGn3TdGk4 // Play: https://go.dev/play/p/GEyGn3TdGk4
func DispatchingStrategyRandom[T any](msg T, index uint64, channels []<-chan T) int { func DispatchingStrategyRandom[T any](msg T, index uint64, channels []<-chan T) int {
for { for {
i := rand.IntN(len(channels)) i := xrand.IntN(len(channels))
if channelIsNotFull(channels[i]) { if channelIsNotFull(channels[i]) {
return i return i
} }
@@ -115,7 +115,7 @@ func DispatchingStrategyWeightedRandom[T any](weights []int) DispatchingStrategy
return func(msg T, index uint64, channels []<-chan T) int { return func(msg T, index uint64, channels []<-chan T) int {
for { for {
i := seq[rand.IntN(len(seq))] i := seq[xrand.IntN(len(seq))]
if channelIsNotFull(channels[i]) { if channelIsNotFull(channels[i]) {
return i return i
} }
+3 -3
View File
@@ -5,7 +5,7 @@ import (
"time" "time"
"github.com/samber/lo/internal/constraints" "github.com/samber/lo/internal/constraints"
"github.com/samber/lo/internal/rand" "github.com/samber/lo/internal/xrand"
) )
// IndexOf returns the index at which the first occurrence of a value is found in a slice or -1 // IndexOf returns the index at which the first occurrence of a value is found in a slice or -1
@@ -660,7 +660,7 @@ type randomIntGenerator func(n int) int
// Sample returns a random item from collection. // Sample returns a random item from collection.
// Play: https://go.dev/play/p/vCcSJbh5s6l // Play: https://go.dev/play/p/vCcSJbh5s6l
func Sample[T any](collection []T) T { func Sample[T any](collection []T) T {
result := SampleBy(collection, rand.IntN) result := SampleBy(collection, xrand.IntN)
return result return result
} }
@@ -677,7 +677,7 @@ func SampleBy[T any](collection []T, randomIntGenerator randomIntGenerator) T {
// Samples returns N random unique items from collection. // Samples returns N random unique items from collection.
// Play: https://go.dev/play/p/vCcSJbh5s6l // Play: https://go.dev/play/p/vCcSJbh5s6l
func Samples[T any, Slice ~[]T](collection Slice, count int) Slice { func Samples[T any, Slice ~[]T](collection Slice, count int) Slice {
results := SamplesBy(collection, count, rand.IntN) results := SamplesBy(collection, count, xrand.IntN)
return results return results
} }
+4
View File
@@ -0,0 +1,4 @@
# Constraints
This package is for Go 1.18 retrocompatiblity purpose.
@@ -1,6 +1,6 @@
//go:build !go1.22 //go:build !go1.22
package rand package xrand
import "math/rand" import "math/rand"
@@ -1,6 +1,6 @@
//go:build go1.22 //go:build go1.22
package rand package xrand
import "math/rand/v2" import "math/rand/v2"
+3 -3
View File
@@ -10,7 +10,7 @@ import (
"github.com/samber/lo" "github.com/samber/lo"
"github.com/samber/lo/internal/constraints" "github.com/samber/lo/internal/constraints"
"github.com/samber/lo/internal/rand" "github.com/samber/lo/internal/xrand"
) )
// IndexOf returns the index at which the first occurrence of a value is found in a sequence or -1 // IndexOf returns the index at which the first occurrence of a value is found in a sequence or -1
@@ -453,7 +453,7 @@ func NthOrEmpty[T any, N constraints.Integer](collection iter.Seq[T], nth N) T {
// Will iterate through the entire sequence and allocate a slice large enough to hold all elements. // Will iterate through the entire sequence and allocate a slice large enough to hold all elements.
// Long input sequences can cause excessive memory usage. // Long input sequences can cause excessive memory usage.
func Sample[T any](collection iter.Seq[T]) T { func Sample[T any](collection iter.Seq[T]) T {
return SampleBy(collection, rand.IntN) return SampleBy(collection, xrand.IntN)
} }
// SampleBy returns a random item from collection, using randomIntGenerator as the random index generator. // SampleBy returns a random item from collection, using randomIntGenerator as the random index generator.
@@ -468,7 +468,7 @@ func SampleBy[T any](collection iter.Seq[T], randomIntGenerator func(int) int) T
// Will iterate through the entire sequence and allocate a slice large enough to hold all elements. // Will iterate through the entire sequence and allocate a slice large enough to hold all elements.
// Long input sequences can cause excessive memory usage. // Long input sequences can cause excessive memory usage.
func Samples[T any, I ~func(func(T) bool)](collection I, count int) I { func Samples[T any, I ~func(func(T) bool)](collection I, count int) I {
return SamplesBy(collection, count, rand.IntN) return SamplesBy(collection, count, xrand.IntN)
} }
// SamplesBy returns N random unique items from collection, using randomIntGenerator as the random index generator. // SamplesBy returns N random unique items from collection, using randomIntGenerator as the random index generator.
+6 -6
View File
@@ -4,11 +4,11 @@ package it
import ( import (
"iter" "iter"
"math/rand/v2"
"slices" "slices"
"testing" "testing"
"time" "time"
"github.com/samber/lo/internal/xrand"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -687,8 +687,8 @@ func TestSampleBy(t *testing.T) {
t.Parallel() t.Parallel()
is := assert.New(t) is := assert.New(t)
result1 := SampleBy(values("a", "b", "c"), rand.IntN) result1 := SampleBy(values("a", "b", "c"), xrand.IntN)
result2 := SampleBy(values[string](), rand.IntN) result2 := SampleBy(values[string](), xrand.IntN)
is.True(Contains(values("a", "b", "c"), result1)) is.True(Contains(values("a", "b", "c"), result1))
is.Empty(result2) is.Empty(result2)
@@ -714,14 +714,14 @@ func TestSamplesBy(t *testing.T) {
t.Parallel() t.Parallel()
is := assert.New(t) is := assert.New(t)
result1 := SamplesBy(values("a", "b", "c"), 3, rand.IntN) result1 := SamplesBy(values("a", "b", "c"), 3, xrand.IntN)
result2 := SamplesBy(values[string](), 3, rand.IntN) result2 := SamplesBy(values[string](), 3, xrand.IntN)
is.ElementsMatch(slices.Collect(result1), []string{"a", "b", "c"}) is.ElementsMatch(slices.Collect(result1), []string{"a", "b", "c"})
is.Empty(slices.Collect(result2)) is.Empty(slices.Collect(result2))
type myStrings iter.Seq[string] type myStrings iter.Seq[string]
allStrings := myStrings(values("", "foo", "bar")) allStrings := myStrings(values("", "foo", "bar"))
nonempty := SamplesBy(allStrings, 2, rand.IntN) nonempty := SamplesBy(allStrings, 2, xrand.IntN)
is.IsType(nonempty, allStrings, "type preserved") is.IsType(nonempty, allStrings, "type preserved")
} }
+2 -2
View File
@@ -1,6 +1,6 @@
package mutable package mutable
import "github.com/samber/lo/internal/rand" import "github.com/samber/lo/internal/xrand"
// Filter is a generic function that modifies the input slice in-place to contain only the elements // Filter is a generic function that modifies the input slice in-place to contain only the elements
// that satisfy the provided predicate function. The predicate function takes an element of the slice and its index, // that satisfy the provided predicate function. The predicate function takes an element of the slice and its index,
@@ -55,7 +55,7 @@ func MapI[T any, Slice ~[]T](collection Slice, fn func(item T, index int) T) {
// Shuffle returns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm. // Shuffle returns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm.
// Play: https://go.dev/play/p/2xb3WdLjeSJ // Play: https://go.dev/play/p/2xb3WdLjeSJ
func Shuffle[T any, Slice ~[]T](collection Slice) { func Shuffle[T any, Slice ~[]T](collection Slice) {
rand.Shuffle(len(collection), func(i, j int) { xrand.Shuffle(len(collection), func(i, j int) {
collection[i], collection[j] = collection[j], collection[i] collection[i], collection[j] = collection[j], collection[i]
}) })
} }
+4 -4
View File
@@ -7,7 +7,7 @@ import (
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/samber/lo/internal/rand" "github.com/samber/lo/internal/xrand"
"golang.org/x/text/cases" "golang.org/x/text/cases"
"golang.org/x/text/language" "golang.org/x/text/language"
@@ -60,14 +60,14 @@ func RandomString(size int, charset []rune) string {
// Determine the corresponding bitmask, // Determine the corresponding bitmask,
// e.g., for 62 characters, the bitmask would be 111111. // e.g., for 62 characters, the bitmask would be 111111.
var letterIDMask int64 = 1<<letterIDBits - 1 var letterIDMask int64 = 1<<letterIDBits - 1
// Available count, since rand.Int64() returns a non-negative number, the first bit is fixed, so there are 63 random bits // Available count, since xrand.Int64() returns a non-negative number, the first bit is fixed, so there are 63 random bits
// e.g., for 62 characters, this value is 10 (63 / 6). // e.g., for 62 characters, this value is 10 (63 / 6).
letterIDMax := 63 / letterIDBits letterIDMax := 63 / letterIDBits
// Generate the random string in a loop. // Generate the random string in a loop.
for i, cache, remain := size-1, rand.Int64(), letterIDMax; i >= 0; { for i, cache, remain := size-1, xrand.Int64(), letterIDMax; i >= 0; {
// Regenerate the random number if all available bits have been used // Regenerate the random number if all available bits have been used
if remain == 0 { if remain == 0 {
cache, remain = rand.Int64(), letterIDMax cache, remain = xrand.Int64(), letterIDMax
} }
// Select a character from the charset // Select a character from the charset
if idx := int(cache & letterIDMask); idx < len(charset) { if idx := int(cache & letterIDMask); idx < len(charset) {