2.0.0
A major release: critical correctness fixes, a rework of the library's concurrency
story, removal of APIs that didn't make sense, and a batch of new generators. If you are
coming from 1.x, build against 1.3.0 first — it deprecates everything 2.0 removes, with
messages naming the replacements.
Concurrency: RandomGenerator no longer requires Sendable
Generators are ordinary values, confined to the isolation domain where they are built
and run:
- The protocol requires neither
SendablenorElement: Sendable. Conformers may hold
non-Sendable state and produce non-Sendable values. - Transform closures (
map,flatMap,filter,retry,tryMap, ...) are plain
closures — they can capture anything the surrounding context can. - Leaf generators (
IntGenerator,FloatGenerator,BoolGenerator,Always,
Character,UnicodeScalar, the seeded RNGs, and all ready-made generators) declare
Sendableexplicitly, and closure-free combinators (Array,Collect,Concat,
Dictionary,Element,Frequency,OneOf,OrNil,Print,Shuffled,Tuple,
Zip, ...) propagate it conditionally — so leaf-only compositions remain shareable. RemoveDuplicatesdrops its lock and@unchecked Sendable; the compiler now enforces
its single-domain confinement.AttemptBounded.FallbackStrategyis no longerSendable(it carries a closure).
Migration: pipelines containing closures are no longer Sendable. Move one into a
Task and region isolation checks the transfer; to use a pipeline from several tasks,
build one per task.
Fixed
AnyRandomGeneratornever advanced the caller's RNG — erased generators (including
the character presets) replayed the same value forever under a seeded RNG. Seeded
sequences involving erased generators change with this fix.Zip(...).map { a, b, c in }compiles again on Swift 6.3 via a pack-argument overload.compactMap/retryMapcould crash on a force-unwrap when the attempt budget was
exhausted; they now produceOptional(nil on exhaustion).retryThrowingproduces
Result(the last failure on exhaustion), runs its transform once per candidate, and
no longer backstops withfatalError.uiColor(alpha:)/swiftUIColor(alpha:)silently ignored their alpha parameter; the
parameter is removed and the generator'sinit(alpha:)visibly governs.UnicodeScalar/Charactergeneration over ranges spanning the surrogate gap
(U+D800–DFFF) no longer biases toward the lower bound or traps; the gap is skipped
uniformly.Frequencyno longer materializes a sum-of-all-weights array on every run (cumulative
bounds + one draw), and fails fast with clear preconditions on empty or all-zero
distributions.AttemptBoundedcounts the initial run towardmaxAttempts(previously
maxAttempts: 3ran the upstream up to 4 times);maxAttemptsmust be ≥ 1.IntGenerator(in: 0..<0)traps with a clear message instead of a confusing
ClosedRangeprecondition.- The package declared iOS 13 but could not compile for iOS at all (
Zip's parameter
packs require the iOS 17 runtime). Platforms are now honestly declared —
iOS 13 / macOS 10.15 / tvOS 13 / watchOS 6 — with onlyZipand its operators gated
behind@available(macOS 14, iOS 17, tvOS 17, watchOS 10). IPAddressGeneratorimports Foundation explicitly.
Added
RandomGenerators.Bernoulli/.bool(probability:)— biased coin.orNil(probability:)— produce nil with a given probability.RandomGenerators.Normal(Box–Muller) andRandomGenerators.Exponential
distributions, with.normal(mean:standardDeviation:)/.exponential(rate:)sugar.RandomGenerators.oneOf(...)— uniform pick across 2–4 generators of different
concrete types sharing an element type.RandomGenerators.string(of:count:)andcharacterGen.string(count:).- Seeded RNGs:
Xoshiro256(xoshiro256++),SplitMix64,PCG(independent streams via
sequence:). Dice(sides:)withd4/d6/d8/d10/d12/d20/d100presets.- Dot-syntax statics:
.int(in:),.float(in:),.bool. RandomGenerators.sudoku(difficulty:)convenience.- DocC catalogs for both modules and the swift-docc-plugin.
- A runnable example target exercising the whole API.
Changed (breaking)
BoolRandomGeneratoris renamedBoolGenerator(deprecated typealias retained).compactMap/retryMapproduceOutput?;retryThrowingproduces
Result<Output, Error>.Frequencyis constructed viaRandomGenerators.frequency(_:); the receiver-ignoring
instance method is removed.UnicodeScalarandCharacterare standalone generators constructed from a range;
the combinator forms (whose upstream was ignored) are removed.
Removed
ZipArrayGenerator,zipAll(),zipGenerators(...)— exact duplicates ofCollect;
use[generators].collect().gen.always(_:),gen.colorGenerator(alpha:)— receiver-ignoring factories; construct
Always(_:)/ColorGenerator(alpha:)directly.CreditCardGenerator.Generated— useElement.