为什么Linq没有头和尾?

uurity8g  于 2023-09-28  发布在  其他
关注(0)|答案(4)|浏览(95)

我经常发现自己想在IEnumerables上使用Head和Tail方法,这在Linq中并不存在。虽然我可以很容易地写我自己的,但我想知道他们是否被故意遗漏了。比如说,

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);
}

那么,使用Linq的最佳实践是什么呢?我一直在寻找它的用途,这是否表明我没有做一些推荐的事情?如果不是,那么为什么在Linq中没有实现这种常见的函数范式呢?

xeufq47z

xeufq47z1#

从技术上讲,你的头是.First(),你的尾是.Skip(1)。但也许你能找到更好的解决办法?比如在IEnumerable上使用.Aggregate()

b1zrtrql

b1zrtrql2#

鉴于IEnumerable<T>的接口,性能并不总是能够得到保证。
您注意到大多数函数式编程语言都实现了tail和head。然而,应该注意的是,这些语言是在记忆结构中起作用的。
IEnumerable<T>没有任何这样的约束,因此不能假定这是有效的。
例如,一个常见的函数模式是递归地处理集合的头部,然后递归地处理调用的尾部。
例如,如果您使用Entity Framework执行此操作,您将向SQL Server发送以下(Meta)调用,紧密循环。

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

这将是非常低效的。
编辑:
仔细想想。另一个原因是C#/VB.NET不支持尾递归,因此,这种模式很容易导致StackOverflow

hc2pp10m

hc2pp10m3#

因为“Head & Tail”概念在pattern matching和递归调用的函数式编程中使用。由于C#不支持模式匹配,因此不需要实现head()和tail()方法。

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

至于你的情况-你应该使用Aggregate方法。

km0tfn4u

km0tfn4u4#

我并不是建议在生产代码中使用这种方法,但我试图向一些了解C#的朋友解释Haskell代码片段,并发现我可以通过混合IEnumerable<T>IEnumerator<T>来实现这一点(你可以,因为IEnumerable总是给你GetEnumerator(),你可以使用迭代器(yield return)将IEnumerator转换为IEnumerable。迭代器为您提供了模拟惰性的好处(在某些上下文中,如果使用正确)。

IEnumerable<int> sieve(IEnumerable<int> l)
{
    var (p, xs) = getHeadAndTail(l);
    yield return p;
    foreach (var n in sieve(xs.Where(i => i % p > 0)))
        yield return n;
}

(T, IEnumerable<T>) getHeadAndTail<T>(IEnumerable<T> l)
{
    var e = l.GetEnumerator();
    e.MoveNext();
    var head = e.Current;
    return (head, tailGetter());

    IEnumerable<T> tailGetter()
    {
        while (e.MoveNext())
            yield return e.Current;
    }
}

(to纯粹主义者-在原始上下文中,这两个都是局部函数,因此它们以小写字母开头)
我怀疑有一种方法可以做到这一点,而不(显式地)引入IEnumerator(可能仍然涉及迭代器),但我还没有偶然发现它。
(在今天闲逛时,我刚刚发现IEnumerator<T>实现了IDisposable,而IEnumerator没有。Geez,the stuff ya never notice(天啊,你从来没有注意到的东西)

相关问题