diff --git a/README.md b/README.md
index 85d23832..20f1985b 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,9 @@
- Lib package: [](https://www.nuget.org/packages/ImTools.dll)
- Code package: [](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]