Skip to content

Aff, Eff, AtomHashMap, TrackingHashMap + fixes [RTM]

Compare
Choose a tag to compare
@louthy louthy released this 10 May 14:27
· 845 commits to main since this release

Language-ext had been in beta for a few months now. Today we go back to full 'RTM' mode.

The recent changes are:

AtomHashMap and Ref change-tracking

A major new feature that allows for tracking of changes in an AtomHashMap or a Ref (using STM). The Change event publishes HashMapPatch<K, V> which will allow access to the state of the map before and after the change, as well as a HashMap<K, Change<V>> which describes the transformations that took place in any transactional event.

In the LanguageExt.Rx project there's various observable stream extensions that leverage the Change event:

  • OnChange() - which simply streams the HashMapPatch<K, V>
  • OnEntryChange() - which streams the Change<V> for any key within the map
  • OnMapChange() - which streams the latest HashMap<K, V> snapshot

Ref which represents a single value in the STM system, has a simpler Change event that simply streams the latest value. It also has an Rx extension, called Change().

Documented in previous beta release notes

TrackingHashMap<K, V>

This is a new immutable data-structure which is mostly a clone of HashMap; but one that allows for changes to be tracked. This is completely standalone, and not related to the AtomHashMap in any way other than it's used by the AtomHashMap.Swap method. And so, this has use-cases of its own.

Changes are tracked as a HashMap<K, Change<V>>. That means there's at most one change-value stored per-key. So, there's no risk of an ever expanding log of changes, because there is no log! The changes that are tracked are from the 'last snapshot point'. Which is from the empty-map or from the last state where tracking HashMap.Snapshot() is called.

Documented in previous beta release notes

Fixes to the Aff and Eff system

The Aff and Eff system had some unfortunate edge-cases due to the use of memoisation by-default. The underlying system has been simplified to be more of a standard reader-monad without memoisation. You can still memoise if needed by calling: ma.Memo().

Future changes will make the Aff and Eff into more of a DSL, which will allow for certain elements of the system to be 'pure', and therefore safely memoisable, and other elements not. My prototype of this is in too early a stage to release though, so I've taken the safer option here.

Breaking change: Both Clone and ReRun have been removed, as they are now meaningless.

New package LanguageExt.SysX - for .NET5.0+ features

The LanguageExt.Sys package is a wrapper for .NET BCL IO functionality, for use with the runtime Eff and Aff monads. This is going to stay as netstandard2.0 for support of previous versions of the .NET Framework and .NET Core. This new package adds features that are for net5.0+.

The first feature to be supported is the Activity type for Open-Telemetry support.

ScheduleAff and ScheduleEff usage was inconsistent

Depending on the monad they were used with, you might see a 'repeat' that was 1 greater than it should have been. This is now fixed.

Lazy Seq equality fix

Under certain rare circumstances it was possible for the equality operator to error with a lazy Seq. Fix from @StefanBertels - thanks!

No more empty array allocations

It seams c# isn't smart enough to turn a new A[0] into a non-allocating operation. And so they have all been replaced with Array.Empty(). Fix from @timmi-on-rails - thanks!

Any problems, please report them in the Issues as usual. Paul 👍