Can I cache partially-executed LINQ queries?

c#, linq

Solution

Sure, that's totally doable:

public static Func<A, double> ThrowIfNegative<A, double>(this Func<A, double> f)
{
    return a=>
    { 
      double r = f(a);  
      // if r is NaN then this will throw.
      if ( !(r >= 0.0) )
        throw new Exception(); 
      return r;
    };
}

public static Func<A, R> Memoize<A, R>(this Func<A, R> f)
{
    var d = new Dictionary<A, R>();
    return a=>
    {
        R r;
        if (!d.TryGetValue(a, out r))
        {
          r = f(a);
          d.Add(a, r);
        }
        return r;
    };
}

And now...

Func<T, double> weight = whatever;
weight = weight.ThrowIfNegative().Memoize();

and you're done.

Problem

I have the following code: ``` IEnumerable<KeyValuePair<T, double>> items = sequence.Select(item => new KeyValuePair<T, double>(item, weight(item))); if (items.Any(pair => pair.Value<0)) throw new ArgumentException("Item weights cannot be less than zero."); double sum = items.Sum(pair => pair.Value); foreach (KeyValuePair<T, double> pair in items) {...} ``` Where `weight` is a `Func<T, double>`. The problem is I want `weight` to be executed as few times as possible. This means it should be executed at most once for each item. I could achieve this by saving it to an array. However, if any weight returns a negative value, I don't want to continue execution. Is there any way to accomplish this easily within the LINQ framework?

Original source