SodaFlow.Core 5.0.0

dotnet add package SodaFlow.Core --version 5.0.0
                    
NuGet\Install-Package SodaFlow.Core -Version 5.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SodaFlow.Core" Version="5.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SodaFlow.Core" Version="5.0.0" />
                    
Directory.Packages.props
<PackageReference Include="SodaFlow.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SodaFlow.Core --version 5.0.0
                    
#r "nuget: SodaFlow.Core, 5.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SodaFlow.Core@5.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SodaFlow.Core&version=5.0.0
                    
Install as a Cake Addin
#tool nuget:?package=SodaFlow.Core&version=5.0.0
                    
Install as a Cake Tool

SodaFlow - Functional Reactive Programming (FRP) library for .NET core library.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 is compatible.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on SodaFlow.Core:

Package Downloads
SodaFlow

SodaFlow - Functional Reactive Programming (FRP) library for .NET.

SodaFlow.Bindable.ObjectModel.Core

SodaFlow Bindable Object Model library for .NET core library.

SodaFlow.Async.Core

SodaFlow Async Extensions library for .NET core library.

SodaFlow.FSharp

SodaFlow - Functional Reactive Programming (FRP) library for F#.

SodaFlow.Collections.Core

SodaFlow Reactive Collections library for .NET core library.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
5.0.0 655 9/28/2026
4.0.2 510 9/18/2026
4.0.1 315 9/18/2026
4.0.0 1,258 9/6/2026
3.0.0 388 8/30/2026
2.1.1 192 8/30/2026
2.1.0 202 8/30/2026
2.0.0 383 8/29/2026
1.0.0 265 8/27/2026

5.0.0

Adds StreamExtensionMethodsInternal.DebounceImpl, which each language surface
gives as a debounce of a stream. It fires the last value after a time with no
other value, and each firing moves the alarm out. The method takes the clock,
a function that makes an alarm from a cell, a function that arms a deadline, and
the value for no deadline. Thus, it holds no optional type, as FilterSomeImpl
does not.

PostImpl takes one more argument, for the packages that reach these internals
and for the public Post that SodaFlow and SodaFlow.FSharp give: the action to
run where the posted action does not run or does not complete. A transaction
that fails while it propagates discards each action that Post holds. Code that
gives a value to something which waits, and gives that value from a posted
action, had no way to release it, thus the waiting code waited forever.

The release runs one time, and only where the posted action does not complete.
Two conditions give that: the transaction fails before it runs the action, and
the action itself throws. The argument is the exception of the transaction in
the first condition, and the exception of the action in the second. An action
that completes runs no release.

A throw from a release does not stop the release of another posted action, and
it does not replace the exception that caused it. The caller gets an
AggregateException with that exception first and the throw from the release
after it, thus no code loses a failure.

The release belongs to one posted action, at the call that posts it, and not to
a transaction. Thus, no code can ask for a release with nothing to release, and
none must find the transaction that is open to ask.

SodaFlow.Core.Async is the first caller. Its Execute gives a Task to code that
waits, and it gives the value of that Task from a posted action.

Adds SnapshotLatestImpl, for the SnapshotLatest that SodaFlow and
SodaFlow.FSharp give. It samples a behavior when a stream fires, as SnapshotImpl
does. SnapshotImpl gives the value from before the transaction. SnapshotLatestImpl
gives the value at the end of the transaction.

It uses the mechanism of LiftImpl. The stream and the updates of the behavior
send into one pulse. A coalesce operation that ranks above both reads the
captured update. Thus, the behavior can update before the output fires. A stream
that fires more than once in a transaction gives one output firing for each, as
SnapshotImpl does.

SnapshotLatestImpl takes up to eight behaviors or cells. All of its forms use one
private method. Each form gives a capture for each behavior, a function that
reads the captured values, and the function that puts them together. The
captures are StreamInternal.Pulse on the updates of each behavior. The reads are
Behavior.Take, which LiftImpl also uses, and which is internal now and not
private.

Adds MergeMaybesImpl, for the Merge of streams of different types that SodaFlow
and SodaFlow.FSharp give. It takes two to eight streams and a function
that gets one MaybeInternal for each stream. The mechanism is the one of
LiftImpl, with streams in place of the updates of behaviors. Each stream
captures its firing and sends into one pulse. A coalesce operation that ranks
above the pulse makes one output firing from the captured values. This is less
expensive than a merge of mapped streams, and no stream has priority.

LiftImpl takes up to eight behaviors or cells, where it took up to six, and
SnapshotImpl takes up to eight, where it took up to four. They are for the wider
Lift and Snapshot that SodaFlow gives. Each new form is the form before it with
one more input.

The name is not MergeImpl. With that name, the F# type inference at the call in
mergeOptions2 also uses the MergeImpl for streams of one type. Thus,
mergeOptions2 accepts only two streams of one type. The F# package builds without an
error, and a call with two types fails only in the code that calls it.

StreamInternal.Pulse is new. It connects a stream to a pulse, and it takes the
place of the private Behavior.Pulse, which connected only the updates of a
behavior. LiftImpl, SnapshotLatestImpl, and MergeMaybesImpl call it, and give it
the updates of a behavior where the input is a behavior.

BREAKING for the packages that reach these internals: AttachListenerImpl is
named AttachListenerInternal. The Impl suffix here marks a method that a public
extension forwards to, and the extension that forwarded to this one is gone from
SodaFlow and SodaFlow.FSharp, so the name follows the one HoldInternal and
HoldLazyInternal use for a method with no public counterpart. Only those two
packages called it, and both move with this release.

BREAKING for the packages that reach these internals, though this assembly has
no public API of its own to move: ListenOnceImpl returns IWeakListener, where it
returned IStrongListener, and ListenOnceStrongImpl is new and returns what
ListenOnceImpl used to. Internal is not private here - this assembly grants
InternalsVisibleTo to the shipping packages around it - so a SodaFlow or a
SodaFlow.FSharp built against 4.x names a method whose return type has changed
and cannot bind to it at run time. Both of those packages carry 5.0.0 as their
floor. No other package calls either method.

The two one-shot listeners are one generic method now rather than two copies of
the same thirty lines, which is what the split would otherwise have created.
Nothing about the sequence changed: the listener stops itself at the first
value, a value that the call to listen sends again unlistens early, and the
caller gets a listener that does nothing in that case.

This is the last of the rename that 2.0.0 began. That release swapped ListenImpl
to the weak listener and removed ListenWeakImpl; ListenOnceImpl kept the old
meaning until now, and was the one name left where the short form rooted the
stream.

4.0.2

Adds the package icon that nuget.org shows beside this package. No source file
changed since 4.0.1.

4.0.1

Grants InternalsVisibleTo to the three collections assemblies:
SodaFlow.Core.Collections, SodaFlow.Collections and
SodaFlow.FSharp.Collections.

Required rather than cosmetic, for the reason 2.1.0 was. The CLR checks
the friend-assembly attribute on the assembly that declares the
internals, so those three throw MethodAccessException at run time
against a 4.0.0 core, even though they build cleanly from source, where
the grants are present. Anything depending on SodaFlow.Collections or
SodaFlow.FSharp.Collections needs this version, and both carry it as
their floor.

No other change, public or internal.

4.0.0

BREAKING: internal members are gone or changed shape. Internal is not
private here - this assembly grants InternalsVisibleTo to the shipping
packages around it, so what it declares internal is API to them, and
removing any of it is a break they have to be rebuilt against.

Gone: TransactionInternal.IsActiveImpl, its parameterless constructor,
Close and the Post overload; the Utilities class and its Yield;
MaybeInternal's NoneType, the None field and the implicit conversion
from it; the three Lazy overloads of
LazyExtensionMethodsInternal.LiftImpl; LazyBehavior's LazyInitialValue;
TransactionInternal's ActionEntry and its Entry.IsRemoved.
TransactionInternal.Split returns void where it returned UnitInternal,
which is a different method to a compiler and to the runtime.

Added: the NoListener type, and an Equals overload on MaybeInternal
taking its own type rather than object.

The public surface is unchanged. Every type this package exposes -
Stream, Cell, Behavior, their sinks and loops - has the same members it
had in 3.0.0, so code which only uses the published API needs nothing
but the recompile a new major asks for.

A major rather than a 3.x, and the version is doing real work. Published
SodaFlow.FSharp 3.1.0 calls TransactionInternal.IsActiveImpl and depends
on this package as [3.0.0, 4.0.0). Shipped as 3.0.1 or 3.1.0 this would
resolve against that package and fail when the call was made; shipped as
4.0.0 it falls outside the range and NuGet declines the pairing instead.
That is the whole reason the ranges carry an upper bound.

Requires System.ValueTuple 4.6.2, where it required 4.4.0. Nothing here
uses it differently: this repository named two versions of it, one in
the shipping projects and one in the test projects, and now names a
single version in both. A consumer does nothing about this; NuGet
resolves the higher floor.

3.0.0

BREAKING: FilterMaybeImpl and FilterMaybeInternal are renamed to FilterSomeImpl
and FilterSomeInternal, following the rename in SodaFlow and SodaFlow.FSharp.

These are declared internal, but internal is not private here. This assembly
grants InternalsVisibleTo to eight shipping packages - SodaFlow,
SodaFlow.FSharp, SodaFlow.Core.Async, SodaFlow.Async, SodaFlow.FSharp.Async and
the three bindable object model packages - so anything internal is API as far
as they are concerned, and renaming one breaks them exactly as renaming a
public member would. A wrapper compiled against the old names throws
MissingMethodException against this version.

That is why this is a major version even though nothing changed for a caller
outside those eight.

No one has to remember that. Every package here now declares the range of this
one it was built against, bounded at the next major, so NuGet refuses a pairing
that would fail rather than resolving it and leaving the failure until someone
runs the code. SodaFlow and SodaFlow.FSharp ship alongside this release; the
async and bindable object model packages follow with compatibility releases,
each of which moves a dependency range and nothing else.

2.1.1

Adds the release notes below. 2.1.0 shipped with the repository-wide notes
instead, which described the 2.0.0 listen rename and said nothing about what
2.1.0 actually changed. No code change since 2.1.0.

2.1.0

Grants InternalsVisibleTo to the three bindable object model assemblies:
SodaFlow.Core.Bindable.ObjectModel, SodaFlow.Bindable.ObjectModel and
SodaFlow.FSharp.Bindable.ObjectModel.

Required rather than cosmetic. The CLR checks the friend-assembly attribute on
the assembly that declares the internals, so those three throw
MethodAccessException at run time against a 2.0.0 core - even though they
build cleanly from source, where the grants are present. Anything depending on
SodaFlow.Bindable.ObjectModel needs this version.

No API change otherwise.

2.0.0

Fixed: Cell.updates is volatile, so its lazily created stream is published
safely on weak memory models. It was read outside the transaction lock with
nothing ordering the write, letting a reader observe a partly constructed
object on arm64.

Calm is expressed over CarryState rather than duplicating its state protocol,
and a throwing transaction now releases all five of its queues rather than
three.

Breaking for the packages that reach these internals, though no public API
moved: ListenImpl kept its name and swapped from the strong listener to the
weak one, and ListenWeakImpl is gone.

---

About this package

The engine: Stream<T>, Cell<T>, Behavior<T>, Transaction, the listener
interfaces, and the dependency graph that makes updates atomic. Language
neutral, and not installed directly - take SodaFlow for C# or SodaFlow.FSharp
for F#, both of which bring it with them and expose its operations.

Full notes: https://github.com/MorseCode-Software/SodaFlow/releases