Question

I often find myself wanting to use Head and Tail methods on IEnumerables, which don't exist as part of Linq. While I could easily write my own I wonder whether they have been purposefully left out. For example,

var finalCondition = new Sql("WHERE @0 = @1", conditions.Head().Key, conditions.Head().Value);
foreach (var condition in conditions.Tail())
{
  finalCondition.Append("AND @0 = @1", condition.Key, condition.Value);
}

So, what is the best practice regarding this with Linq? Is the fact that I keep finding uses for this a sign that I am not doing something recommended? If not then why was this common functional paradigm not implemented in Linq?

Was it helpful?

Solution 2

Given the interface of IEnumerable<T>, performance can not always be ensured.

You note that most functional programming languages implement tail and head. However it should be noted that these languages are acting on in memory constructs.

IEnumerable<T> does not have any such constraints, and thus it cannot be assumed that this would be efficient.

A common functional pattern for example would be to recursively work on the Head of a collection and then recurse on the Tail of the call...

If you did this with Entity Framework for instance, you would send the following (meta) call to the SQL server, tight looped.

Select * from
(
    Select * from
    (
         Select * from
         (...)
         Skip 1
    )
    Skip 1
);

Which would be highly inefficient.

EDIT:

Come to think about it. Another reason, is that C#/VB.Net doesn't support tail recursion, and thus, this pattern can easily cause a StackOverflow.

OTHER TIPS

Technically, your Head would be .First() and your Tail would be .Skip(1). But maybe you can find a better solution? Like using .Aggregate() on your IEnumerable?

Because the "Head & Tail" concept is used in functional programming for pattern matching and recursive calls. Since C # does not support pattern matching, then there is no need to implement head() and tail () methods.

let rec sum = function
  | [] -> 0
  | h::t -> h + sum t

As for your case - you should use Aggregate method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top