diff --git a/README.md b/README.md index 85d23832..20f1985b 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ - Lib package: [![NuGet Badge](https://buildstats.info/nuget/ImTools.dll)](https://www.nuget.org/packages/ImTools.dll) - Code package: [![NuGet Badge](https://buildstats.info/nuget/ImTools)](https://www.nuget.org/packages/ImTools) -Fast immutable persistent collections and other data structures -with focus on thread-safety without locks. +Latest stable version is [v2.1.0](https://github.com/dadhi/ImTools/releases/tag/v2.1.0) + +Fast and memory-efficient immutable collections and helper data structures. Split from [DryIoc](https://github.com/dadhi/dryioc). diff --git a/nuspecs/ImTools.nuspec b/nuspecs/ImTools.nuspec index 52ee5d77..925e5d22 100644 --- a/nuspecs/ImTools.nuspec +++ b/nuspecs/ImTools.nuspec @@ -17,22 +17,10 @@ FP Performance Simple Functional Immutable Persistent Map Avl 2-3-4 Self Balanced Tree Dictionary Thread-safe Functional Atomic Ref Algebraic Discriminated Union SumType , Box, Item - - GrowingList, ImZipper, StackPool, Unit, Fun extensions with forward pipe operators - - Ref.Swap now accepts state to use closure-less lambdas with less allocations - - ### Details - - https://github.com/dadhi/ImTools/milestone/2 ]]> diff --git a/src/ImTools/ImTools.Experimental.cs b/src/ImTools/ImTools.Experimental.cs index c8d88e2d..eab233c5 100644 --- a/src/ImTools/ImTools.Experimental.cs +++ b/src/ImTools/ImTools.Experimental.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Runtime.CompilerServices; using System.Threading; @@ -1951,8 +1952,11 @@ protected virtual ImMap234 AddOrKeepOrSplitEntry(int key, ref Entry entry, ou /// Lookup for the entry, if not found returns `null`. You can define other Lookup methods on top of it. public virtual Entry GetEntryOrDefault(int key) => null; - /// Folds - public virtual S Fold(S state, Func reduce, ImMap234[] parentStack = null) => state; + /// Fold to fold + public virtual S Fold(S state, Func reduce) => state; + + /// Enumerable + public virtual IEnumerable Enumerate() => Enumerable.Empty(); // todo: @feature add SoftRemove @@ -2004,7 +2008,13 @@ public override Entry GetEntryOrDefault(int key) => key == Key ? this : null; /// - public override S Fold(S state, Func reduce, ImMap234[] parentStack = null) => reduce(this, state); + public override S Fold(S state, Func reduce) => reduce(this, state); + + /// + public override IEnumerable Enumerate() + { + yield return this; + } } /// 2 leafs @@ -2073,8 +2083,15 @@ public override Entry GetEntryOrDefault(int key) => null; /// - public override S Fold(S state, Func reduce, ImMap234[] parentStack = null) => + public override S Fold(S state, Func reduce) => reduce(Entry1, reduce(Entry0, state)); + + /// + public override IEnumerable Enumerate() + { + yield return Entry0; + yield return Entry1; + } } /// 3 leafs @@ -2150,8 +2167,16 @@ public override Entry GetEntryOrDefault(int key) => null; /// - public override S Fold(S state, Func reduce, ImMap234[] parentStack = null) => + public override S Fold(S state, Func reduce) => reduce(Entry2, reduce(Entry1, reduce(Entry0, state))); + + /// + public override IEnumerable Enumerate() + { + yield return Entry0; + yield return Entry1; + yield return Entry2; + } } /// 3 leafs @@ -2260,8 +2285,17 @@ public override Entry GetEntryOrDefault(int key) => null; /// - public override S Fold(S state, Func reduce, ImMap234[] parentStack = null) => + public override S Fold(S state, Func reduce) => reduce(Entry3, reduce(Entry2, reduce(Entry1, reduce(Entry0, state)))); + + /// + public override IEnumerable Enumerate() + { + yield return Entry0; + yield return Entry1; + yield return Entry2; + yield return Entry3; + } } /// 3 leafs @@ -2462,8 +2496,18 @@ public override Entry GetEntryOrDefault(int key) => null; /// - public override S Fold(S state, Func reduce, ImMap234[] parentStack = null) => + public override S Fold(S state, Func reduce) => reduce(Entry4, reduce(Entry3, reduce(Entry2, reduce(Entry1, reduce(Entry0, state))))); + + /// + public override IEnumerable Enumerate() + { + yield return Entry0; + yield return Entry1; + yield return Entry2; + yield return Entry3; + yield return Entry4; + } } /// 2 branches - it is never split itself, but may produce Branch3 if the lower branches are split @@ -2595,8 +2639,18 @@ public override Entry GetEntryOrDefault(int key) => Entry0; /// - public override S Fold(S state, Func reduce, ImMap234[] parentStack = null) => + public override S Fold(S state, Func reduce) => Right.Fold(reduce(Entry0, Left.Fold(state, reduce)), reduce); + + /// + public override IEnumerable Enumerate() + { + foreach (var l in Left.Enumerate()) + yield return l; + yield return Entry0; + foreach (var r in Right.Enumerate()) + yield return r; + } } /// 3 branches @@ -2818,8 +2872,21 @@ public override Entry GetEntryOrDefault(int key) => key == Entry0.Key ? Entry0 : Entry1; /// - public override S Fold(S state, Func reduce, ImMap234[] parentStack = null) => + public override S Fold(S state, Func reduce) => Right.Fold(reduce(Entry1, Middle.Fold(reduce(Entry0, Left.Fold(state, reduce)), reduce)), reduce); + + /// + public override IEnumerable Enumerate() + { + foreach (var l in Left.Enumerate()) + yield return l; + yield return Entry0; + foreach (var m in Middle.Enumerate()) + yield return m; + yield return Entry1; + foreach (var r in Right.Enumerate()) + yield return r; + } } } diff --git a/src/ImTools/ImTools.csproj b/src/ImTools/ImTools.csproj index 4e6b2f92..ed8852f3 100644 --- a/src/ImTools/ImTools.csproj +++ b/src/ImTools/ImTools.csproj @@ -22,22 +22,9 @@ FP Performance Simple Functional Immutable Persistent Map Avl 2-3-4 Self Balanced Tree Dictionary Thread-safe Functional Atomic Ref Algebraic Discriminated Union SumType , Box, Item - - GrowingList, ImZipper, StackPool, Unit, Fun extensions with forward pipe operators - - Ref.Swap now accepts state to use closure-less lambdas with less allocations - - ### Details - - https://github.com/dadhi/ImTools/milestone/2 +- Added fast and more memory efficient Experimental.ImMap234 implementing 2-3-4 tree (#32) ]]> diff --git a/test/ImTools.UnitTests/Experimental.ImMap234Tests.cs b/test/ImTools.UnitTests/Experimental.ImMap234Tests.cs index addea175..13f85a45 100644 --- a/test/ImTools.UnitTests/Experimental.ImMap234Tests.cs +++ b/test/ImTools.UnitTests/Experimental.ImMap234Tests.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using NUnit.Framework; namespace ImTools.Experimental.UnitTests @@ -44,6 +45,8 @@ public void Adding_keys_from_1_to_10_and_checking_the_tree_shape_on_each_additio Assert.AreEqual(5, m.GetValueOrDefault(5)); Assert.AreEqual(6, m.GetValueOrDefault(6)); + CollectionAssert.AreEqual(Enumerable.Range(1, 6), m.Enumerate().Select(x => x.Value)); + m = m.AddOrUpdate(7, 7); Assert.IsInstanceOf.Branch2>(m); Assert.AreEqual(7, m.GetValueOrDefault(7)); @@ -57,6 +60,8 @@ public void Adding_keys_from_1_to_10_and_checking_the_tree_shape_on_each_additio m = m.AddOrUpdate(10, 10); Assert.AreEqual(10, m.GetValueOrDefault(10)); + + CollectionAssert.AreEqual(Enumerable.Range(1, 10), m.Enumerate().Select(x => x.Value)); } [Test]