language-ext v3.4.10 Release Notes

Release Date: 2020-02-19 // 9 days ago
  • 🚀 Unfortunately, the previous release with the latest CodeGeneration.Roslyn build caused problems due to possible bugs in the CodeGeneration.Roslyn plugin system. These issues only manifested in the nuget package version of the LanguageExt.CodeGen and not in my project-to-project tests, giving a false sense of security.

    👀 After a lot of head-scratching, and attempts at making it work, it seems right to roll it back.

    🚚 This also means rolling back to netstandard2.0 so that the old code-gen can work. And so, I have had to also remove the support for IAsyncEnumerable with OptionAsync and EitherAsync until this is resolved.

    🚀 Apologies for anyone who wasted time on the last release and who might be inconvenienced by the removal of IAsyncEnumerable support. I tried so many different approaches and none seemed to be working.

    Issues resolved:

    👌 Improvements:

    • 🐎 Performance improvements for Map and Lst
    • 🐎 Performance improvements for all hashing of collections

    🆓 Any further issues, please feel free to shout on the issues page or gitter.


Previous changes from v3.4.0

  • 🚀 NOTE: I am just investigating some issues with this release relating to the code-gen, keep an eye out for 3.4.3 tonight or tomorrow (12/Feb/2020)

    👍 In an effort to slowly get language-ext to the point where .NET Core 3 can be fully supported (with all of the benefits of new C# functionality) I have taken some baby steps towards that world:

    ⚡️ Updated the references for CodeGeneration.Roslyn to 0.7.5-alpha

    🏗 This might seem crazy, but the CodeGeneration.Roslyn DLL doesn't end up in your final build (if you set it up correctly), and doesn't get used live even if you do. So, if the code generates correctly at build-time, it works. Therefore, including an alpha is low risk.

    👀 I have been testing this with my TestBed and unit-tests and working with the CodeGeneration.Roslyn team and the alpha seems stable.

    🚀 A release of CodeGeneration.Roslyn is apparently imminent, so, if you're not happy with this, then please wait for subsequent releases of language-ext when I've upgraded to the full CodeGeneration.Roslyn release. I just couldn't justify the code-gen holding back the development of the rest of language-ext any more.

    ⚡️ Updated the minimum .NET Framework and .NET Standard versions

    Ecosystem Old New
    .NET Framework net46 net461
    .NET Standard netstandard2.0 netstandard2.1

    👍 OptionAsync<A> and EitherAsync<A> support IAsyncEnumerable<A>

    🚀 The netstandard2.1 release supports IAsyncEnumerable<A> for OptionAsync<A> and EitherAsync<A>. This is the first baby-step towards leveraging some of the newer features of C# and .NET Core.

    pipe prelude function

    👍 Allow composition of single argument functions which are then applied to the initial argument.

    var split= fun((string s) =\> s.Split(' '));var reverse = fun((string[] words) =\> words.Rev().ToArray());var join= fun((string[] words) =\> string.Join(" ", words));var r = pipe("April is the cruellest month", split, reverse, join); //"month cruellest this is April"
    

    ➕ Added Hashable<A> and HashableAsync<A> type-classes

    0️⃣ Hashable<A> and HashableAsync<A> provide the methods GetHashCode(A x) and GetHashCodeAsync(A x). There are lots of Hashable*<A> class-instances that provide default implementations for common types.

    ⚡️ Updates to the [Record] and [Union] code-gen

    0️⃣ The GetHashCode() code-gen now uses Hashable*<A> for default field hashing. Previously this looked for Eq*<A> where the * was the type of the field to hash, now it looks for Hashable*<A>.

    0️⃣ By default Equals, CompareTo, and GetHashCode use:

    // \* == the type-name of the field/propertydefault(Eq\*).Equals(x, y); default(Ord\*).CompareTo(x, y); default(Hashable\*).GetHashCode(x);
    

    0️⃣ To provide the default structural functionality for the fields/properties. Those can now be overridden with The Eq, Ord, and Hashable attributes:

     [Record] public partial struct Person { [Eq(typeof(EqStringOrdinalIgnoreCase))] [Ord(typeof(OrdStringOrdinalIgnoreCase))] [Hashable(typeof(HashableStringOrdinalIgnoreCase))] public readonly string Forename; [Eq(typeof(EqStringOrdinalIgnoreCase))] [Ord(typeof(OrdStringOrdinalIgnoreCase))] [Hashable(typeof(HashableStringOrdinalIgnoreCase))] public readonly string Surname; }
    

    The code above will generate a record where the fields Forename and Surname are all structurally part of the equality, ordering, and hashing. However, the case of the strings is ignored, so:

     { Forename: "Paul", Surname: "Louth" } == { Forename: "paul", Surname: "louth" }
    

    NOTE: Generic arguments aren't allowed in attributes, so this technique is limited to concrete-types only. A future system for choosing the structural behaviour of generic fields/properties is yet to be designed/defined.

    🐛 Bug fixes

    1. Fix for: 'Seq.ToFullString' and 'Seq.ToFullArrayString' ignore the 'separator' argument 🌐 2. Fix for: Lst<T> serialization broken for web forms pages
    2. Fix for: Bug in ToString implementation for unions 🚚 4. Fix for: Set is missing RemoveRange