Skip to content
David Arno edited this page Feb 17, 2020 · 3 revisions

IEnumerable<T> cons

newList = head :: oldList and head :: tail = someList cons support


Introduction to IEnumerable<T> cons methods

"cons" is a common concept in functional programming languages, related to joining and splitting sets of data. In F#, for example, linked lists use the cons operator (::) to add or remove items from the head of the list. Combining this with recursively processing the tail, the whole list can then be iterated over. Conversely, recursively adding items to the tail allows new lists to be built.

Rather than trying to replicate F#'s linked list type, Succinc<T> provides "cons" support for IEnumerable<T>. This implementation offers two features not available to a basic IEnumerable<T> implementation:

  1. Cons can be used to add/remove items from the head of the enumeration, without affecting the original data set.
  2. The new enumeration can be enumerated many times, without re-enumerating the original data. This is achieved via caching the elements when fetched and that cache is used for subsequent enumerations.

Succinct.Functional.ConsExtensionsForIEnumerable methods

The ConsExtensionsForIEnumerable provides a set of extension methods for IEnumerable<T> for creating "cons enumerables" from an IEnumerable<T> implementation.

ToConsEnumerable

public static IConsEnumerable<T> ToConsEnumerable<T>(this IEnumerable<T> collection)

Returns an IConsEnumerable<T> for the enumeration. This IConsEnumerable<T> can be safely enumerated many times, without the need to re-enumerate the original data set. Unlike calling ToList(), the enumeration is not immediately read however, so there is no overhead in performing the conversion.

Cons<T>(T head)

public static IConsEnumerable<T> Cons<T>(this IEnumerable<T> collection, T head)

Returns an IConsEnumerable<T> composed of head as the first element and the collection as subsequent elements.

Cons<T>(IEnumerable<T> head)

public static IConsEnumerable<T> Cons<T>(this IEnumerable<T> collection, IEnumerable<T> head)

This is a diversion away from standard "cons" features, in that it allows an entire collection of items to be added to the front of another collection. It returns an IConsEnumerable<T> composed of the head elements, followed by the the collection as subsequent elements.

var (head, tail) = enumeration

A deconstruct has been added that splits the the cons enumeration into a head and tail "tuple". This feature only works with C# 7 or later.

SuccincT.Functional.IConsEnumerable<T>

Any cons enumeration offered by Succint<T> implements ``IConsEnumerable`. Those implementations offer the following methods:

Cons(T head)

IConsEnumerable<T> Cons(T head)

Returns an IConsEnumerable<T> composed of head as the first element and the current cons enumerable as subsequent elements.

Cons(IEnumerable<T> head)

IConsEnumerable<T> Cons(IEnumerable<T> head)

Returns an IConsEnumerable<T> composed of the head elements, followed by the the current cons enumerable as subsequent elements.

ConsResult<T> Cons<T>()

ConsResult<T> Cons()

Returns a ConsResult<T>, which contains the head and tail parts of the collection. See below for details of ConsResult<T>.

SuccincT.Functional.ConsResult<T>

ConsResult<T> is returned by Cons calls that split a collection into a head and tail. It has two properties:

public Option<T> Head { get; }

If the collection isn't empty, then Head contains the first element of the collection. If the collection is empty, it contains none.

public IConsEnumerable<T> Tail { get; }

Contains the rest of the collection, or a guaranteed empty collection if the the collection prior to Cons was already empty.

Clone this wiki locally