Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Linq not have Head and Tail?

Tags:

c#

linq

head

tail

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?

like image 225
Jim Jeffries Avatar asked Oct 25 '13 08:10

Jim Jeffries


3 Answers

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?

like image 137
nvoigt Avatar answered Oct 01 '22 20:10

nvoigt


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.

like image 26
Aron Avatar answered Oct 01 '22 19:10

Aron


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.

like image 40
Dzmitry Martavoi Avatar answered Oct 01 '22 18:10

Dzmitry Martavoi