About Jolt.NET Libraries

Inspired by the Boost C++ libraries, Jolt.NET aims to complement the .NET Base Class Library (BCL) with algorithms, data structures, and general productivity tools. It is the hope of the authors that the features of Jolt.NET will one day be part of, or represented in the BCL and the .NET Framework.

Jolt.NET Restructuring and Future Features

During my regular day-job and while I work on the Jolt.NET library, I regularly take notes as to what to include in future library releases.  Sometimes, I post the notes immediately to the project site in the form of a work item.  In this case, the work item will usually contain information about a required change in design of an existing feature, or some planned analysis that assures intended feature functionality.  When I don’t post my notes, it is usually because they refer to an incomplete feature idea (i.e. how the feature should work), and I don’t post them so that I can keep focused on working to complete the currently planned release.

This post will cover some of the upcoming new features for Jolt.NET as well as some needed library reorganization.  You can expect future posts with this theme as the active implementation of a pending release nears completion.

New Assemblies

The Jolt assembly is designed to be the analog of the mscorlib.dll assembly from the .NET Framework.  It contains the commonly used types that generally don’t fit anywhere else in the library, and also serves as a core assembly to be used by others within the library.  For simplicity and ease of use, I’d like Jolt.dll to be free of both internal and external dependencies, for violating this guideline means that any assembly linking to Jolt.dll incurs extra baggage which it may or may not use.  Consequently, the FiniteStateMachine (FSM) class (and its helpers) must be moved to a new assembly as they incur a dependency to QuickGraph.

A similar approach must also be taken when implementing the features that enable translation of an FSM to MSAGL and GLEE graphs since the MSAGL and GLEE assemblies are generally not redistributable.  QuickGraph provides separate assemblies that enable use of these frameworks, avoiding runtime errors in the core library when the frameworks are not present.  I plan to adopt a similar approach for the new Jolt FSM assembly.  Also, you will note that the work items for the FSM translation features have been moved out of the Jolt 0.2 release as I want to perform all of the reorganization at the same time.

Functors

This is a task I’ve been eager to take on for some time now, and think it will add great value to the Jolt.NET library.  The goal is to provide predefined functors that eliminate the need for redefining the same kinds of anonymous delegate (or lambda expressions) over and over.  Redefinition, albeit very compact in syntax, often leads to code bloat in the assembly in the form of non-compact IL.  To illustrate, consider the following code that uses two identical lambda expressions to represent a predicate.



using System;

void CreateFunctors()
{
Predicate<int> isEven = x => x % 2 == 0;
Func<int,bool> isNotOdd = x => x % 2 == 0;
}

The resulting IL for this function will yield two additional methods, both identical in functionality and representing each lambda expression.  If you use an optimizing IL compiler, you may be in luck as the compiler might generate the desired compact version of the code.  I’ll discuss this problem further in a future blog post.

Which functors will help reduce code bloat?  I’ve noted the following, which are used extensively in the Jolt libraries, and can be represented as either constructed or open constructed forms of the Action<> and Func<> delegate variants.

  • Idempotency function: f(x) = c, for all x and a predefined constant c
    • Example: f(x) = true, for all x
  • Identity function: f(x) = x, for all x
  • No-op function: f(x) = void; for all x

In addition to these predefined functors, the following utilities will assist reusing existing delegates to create new ones.

  • Adaptor for Func<>: ignores return value making it compatible with Action<>
  • Functor composition: given functions f(x), and g(y), compose a new function h(y) = f(g(y))
  • Parameter binding: given function f(x, y), bind the first parameter of the function to a constant c, creating a new function g(y) = f(c, y)
    • Similarly for the second parameter

Tuples

The goal of a tuple is to provide for a light-weight read/write generic container that defines only fields (i.e. no methods).  Instead of explicitly defining a new type each time you need to store a collection of fields, a tuple allows you to specialize it with the desired field types, creating the desired container.  For example, Tuple<int, string> is a type containing two fields of types int and string, respectively.

For those familiar with anonymous types, tuples may seem redundant .  However, there are some important differences between an anonymous type and a tuple.

  • The type of the tuple is known at design time
  • The fields of a tuple are writable
  • A tuple implements value-based equality semantics

The tuple implementation will be adapted from the Boost Tuple Library.

0 comments: