I was looking for an anwer to question Get next N elements from enumerable didn't find any satisfying and brewed my own. What I came up with was
IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action){
IEnumerable<R> head;
IEnumerable<R> tail = src;
while (tail.Any())
{
head = tail.Take(n);
tail = tail.Skip(n);
yield return action(head);
}
}
What I would really like though, is to have action have a default of t=>t, but I can't figure out how to make that a default argument. The signature IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action = t=>t) gives a syntax error.
My question is, how do I do this?
I suppose this is identical to Specifying a lambda function as default argument but for C# instead of C++
As a side note, I know it doesn't make any syntactical difference, but would it be easier to read if I switched T and R?
Default values have to be constants, and the only constant value for a delegate is a null reference.
I suggest you use overloading instead. Note that t => t wouldn't be valid anyway, unless you know that there's a conversion from IEnumerable<R> to T, which I don't see anywhere.
Aside from the lambda expression validity problem, you could use the null coalescing operator:
IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n,
Func<IEnumerable<R>, T> action = null)
{
action = action ?? (t => t);
...
}
... but that would be sort of abusing it, and you wouldn't be able to tell whether the null was actually from a caller who thought they were passing a non-null value, and would prefer you to raise an ArgumentNullException.
EDIT: Additionally, note that your method is fundamentally problematic - iterating over the chunks will evaluate the original sequence several times (once per chunk) in order to skip the right amount. It would probably be better to write a method which eagerly read each chunk before returning it. We have a similar method in MoreLINQ, called Batch. Note that Batch has exactly the overload mentioned here - and in this case, the t => t works, because the overload has fewer type parameters, so we know the identity conversion is okay.
It's the same for C#: create an overload.
IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n){
return Chunk<T, R>(src, n, t => t);
}
Related
IGrouping supports the ElementAt method to index into the grouping's collection. So why doesn't the square bracket operator work?
I can do something like
list.GroupBy(expr).Select(group => group.ElementAt(0)....)
but not
list.GroupBy(expr).Select(group => group[0]....)
I'm guessing this is because the IGrouping interface doesn't overload the square bracket operator. Is there a good reason why IGrouping didn't overload the square bracket operator to do the same thing as ElementAt?
That is because GroupBy returns an IEnumerable. IEnumerables don't have an indexing accessor
ElementAt<T> is a standard extension method on IEnumerable<T>, it's not a method on IGrouping, but since IGrouping derives from IEnumerable<T>, it works fine. There is no [] extension method because it's not supported by C# (it would be an indexed property, not a method)
That's a bit back to front, all enumerables are supported by (rather than supports, as it's an extension method provided from the outside) ElementAt() but only some are of a type that also support [], such as List<T> or anything that implements IList<T>.
Grouping certainly could implement [] easily enough, but then it would have to always do so, as the API would be a promise it would have to keep on keeping, or it would break code written to the old way if it did break it.
ElementAt() takes a test-and-use approach in that if something supports IList<T> it will use [] but otherwise it counts the appropriate number along. Since you can count-along with any sequence, it can therefore support any enumerable.
It so happens that Grouping does support IList<T> but as an explicit interface, so the following works:
//Bad code for demonstration purpose, do not use:
((IList<int>)Enumerable.Range(0, 50).GroupBy(i => i / 5).First())[3]
But because it's explicit it doesn't have to keep supporting it if there was ever an advantage found in another approach.
The test-and-use approach of ElementAt:
public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index)
{
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) return list[index];
if (index < 0) throw Error.ArgumentOutOfRange("index");
using (IEnumerator<TSource> e = source.GetEnumerator())
{
while (true)
{
if (!e.MoveNext()) throw Error.ArgumentOutOfRange("index");
if (index == 0) return e.Current;
index--;
}
}
}
Therefore gets the optimal O(1) behaviour out of it, rather than the O(n) behaviour otherwise, but without restricting Grouping to making a promise the designers might later regret making.
ElementAt is an extension method (btw highly inefficient) defined for IEnumerable<T> to provide a pseudo-indexed access for the sequences that do not natively support it. Since IGrouping<TKey, TElement> returned from a GroupBy method inherits IEnumerable<TElement>, you can use ElementAt method. But of course IEnumerable<T> does not have an indexer defined, so thta's why you cannot use [].
Update: Just to clarify what I meant by "highly inefficient" - the implementation is the best that could be provided, but the method itself in general for the sequences that do not natively support indexer. For example
var source = Enumerable.Range(0, 1000000);
for (int i = 0, count = source.Count(); i < count; i++)
{
var element = source.ElementAt(i);
}
Say I have the following method:
static int MethodWithDefaultParameters(int a, int b=0, int c=1)
{
return a + b + c;
}
And then I use this method in a LINQ query like so:
Enumerable.Range(1,10).Select(MethodWithDefaultParameters);
This fails with:
Error 1 The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Of course, I can work around this by inserting a lambda that forwards the function call like this:
Enumerable.Range(1,10).Select(i => MethodWithDefaultParameters(i));
But my question is why does the type inference fail? As far as I can tell, it should not be ambiguous as there is only one variant of the function that satisfies the input variable.
There are two overloads for Select(). One that takes as the second parameter (i.e. the delegate) a Func<TSource, TResult>, and one that takes a Func<TSource, int, TResult>. I.e. a method signature with either one parameter or two.
Your method satisfies neither. Even with the default values, it still has three parameters. Default parameters are a compile-time construct and must be provided at the call site. They aren't filled in at run-time via a call to a delegate instance.
So, in fact, your work-around is one of the two reasonable ways to address the problem. The other would be to implement the default parameters differently (i.e. "old-school" :) ):
static int MethodWithDefaultParameters(int a)
{
return MethodWithDefaultParameters(a, 0, 1);
}
static int MethodWithDefaultParameters(int a, int b, int c)
{
return a + b + c;
}
Then you can use MethodWithDefaultParameters in your call to Select() directly, as the compiler will find the single-parameter overload that is compatible with one of the Select() overloads.
I have a generic method that takes Enumerables of type T. In the event that T is also an Enumerable, I need to pass it to another function. However, since that function only takes Enumerables, and T is generic, it won't compile.
I'm checking that T is Enumerable before I pass it - but clearly not in a way that solves this problem.
How can I do this?
(Obviously I could write another method that only takes IEnumerable< IEnumerable< T>>, and use that where relevant, but that seems inelegant.)
Example:
public static bool EnumerablesAreEqual<T>(IEnumerable<T> a, IEnumerable<T> b)
{
foreach (T x in a)
{
if (x is Enumerable && !EnumerableContainsEnumerable(x, b))
return false;
if (!b.Contains(x))
return false;
}
...
}
I've looked at this post but I don't think it's quite the same issue.
The fact that you check the dynamic type of the variable doesn't change its static type, and that what it's used to check the call.
If you want to do that, you need a cast. You can use a checked cast to do it in one go:
Enumerable ex = x as Enumerable;
if (ex != null && !EnumerableContainsEnumerable(ex, b))
return false;
The as operator checks whether the cast is possible: if it is it will return the casted object; if it is not, it will return null.
Let's say I have a list of objects, and I want to sort it by the items DateModified property. Why can't I use a delegate like this? How should I sort these by DateModified if not as shown below:
public string SortByDateModified(List<CartItem> items)
{
items.Sort(new Func<CartItem, CartItem, bool>((itemA, itemB) =>
{
return itemA.DateModified < itemB.DateModified;
}));
}
Why not use a lambda expression?
public string SortByDateModified(List<CartItem> items)
{
items.Sort((a, b) => a.DateModified.CompareTo(b.DateModified));
}
If you don't want to use lambdas or greater than .NET 2.0, use this:
public string SortByDateModified(List<CartItem> items)
{
items.Sort(delegate(CartItem itemA, CartItem itemB)
{
return itemA.DateModified.CompareTo(itemB.DateModified);
});
}
In my experience, in environments such as Unity, lambdas and even delegates can cause crashes or problems, especially on platforms like iOS. In that case you would want to make your sorter a separate function like so:
int SortCartItemFunction(CartItem itemA, CartItem itemB)
{
return itemA.DateModified.CompareTo(itemB.DateModified);
}
Then you could pass it to your sort call like this:
items.Sort(SortCartItemFunction);
The Sort method takes a delegate called Comparison<T>. You're trying to pass in a Func<int, int, bool>, which is itself a delegate. There is no conversion between the delegate Func<int, int, bool> and the delegate Comparison<T>.
You can, however, use a lambda expression.
items.Sort((a, b) => a.DateModified.CompareTo(b.DateModified));
Indeed, you use this very lambda expression and pass it into the Func<int, int, bool> constructor*. However, there is no need. A lambda expression can be converted into any delegate whos signature matches - that is (a, b) => a.DateModified.CompareTo(b.DateModified) can be assigned to something typed Func<int, int, int> or something typed Comparison<T>. In this case we pass it in to something which expects a Comparison<T>.
* With one minor adjustment. Sort expectes an integer as a return type. Negative values indicate less than, 0 indicates equal, and positive values indicate greater than.
bool is not useful in such a delegate, usually int is used because you need 3 values to represent the results of the comparison, less than, equal and greater than. .NET collections usually (if not always) assume -1 means less than, 0 means equal and 1 means greater than.
You would then, in your delegate, have to check if value x is less, equal or greater than value y. An interesting thing to note here is that if you flip the results, for example compare y with x instead you will sort in the opposite direction.
For the easiest way to sort the dates, check JohnC's answer, or Sam's.
I read This article and i found it interesting.
To sum it up for those who don't want to read the entire post. The author implements a higher order function named Curry like this (refactored by me without his internal class):
public static Func<T1, Func<T2, TResult>>
Curry<T1, T2, TResult>(this Func<T1, T2, TResult> fn)
{
Func<Func<T1, T2, TResult>, Func<T1, Func<T2, TResult>>> curry =
f => x => y => f(x, y);
return curry(fn);
}
That gives us the ability to take an expression like F(x, y)
eg.
Func<int, int, int> add = (x, y) => x + y;
and call it in the F.Curry()(x)(y) manner;
This part i understood and i find it cool in a geeky way. What i fail to wrap my head around is the practical usecases for this approach. When and where this technique is necessary and what can be gained from it?
Thanks in advance.
Edited:
After the initial 3 responses i understand that the gain would be that in some cases when we create a new function from the curried some parameters are not re evalued.
I made this little test in C# (keep in mind that i'm only interested in the C# implementation and not the curry theory in general):
public static void Main(string[] args)
{
Func<Int, Int, string> concat = (a, b) => a.ToString() + b.ToString();
Func<Int, Func<Int, string>> concatCurry = concat.Curry();
Func<Int, string> curryConcatWith100 = (a) => concatCurry(100)(a);
Console.WriteLine(curryConcatWith100(509));
Console.WriteLine(curryConcatWith100(609));
}
public struct Int
{
public int Value {get; set;}
public override string ToString()
{
return Value.ToString();
}
public static implicit operator Int(int value)
{
return new Int { Value = value };
}
}
On the 2 consecutive calls to curryConcatWith100 the ToString() evaluation for the value 100 is called twice (once for each call) so i dont see any gain in evaluation here. Am i missing something ?
Currying is used to transform a function with x parameters to a function with y parameters, so it can be passed to another function that needs a function with y parameters.
For example, Enumerable.Select(this IEnumerable<T> source, Func<TSource, bool> selector) takes a function with 1 parameter. Math.Round(double, int) is a function that has 2 parameters.
You could use currying to "store" the Round function as data, and then pass that curried function to the Select like so
Func<double, int, double> roundFunc = (n, p) => Math.Round(n, p);
Func<double, double> roundToTwoPlaces = roundFunc.Curry()(2);
var roundedResults = numberList.Select(roundToTwoPlaces);
The problem here is that there's also anonymous delegates, which make currying redundant. In fact anonymous delegates are a form of currying.
Func<double, double> roundToTwoPlaces = n => Math.Round(n, 2);
var roundedResults = numberList.Select(roundToTwoPlaces);
Or even just
var roundedResults = numberList.Select(n => Math.Round(n, 2));
Currying was a way of solving a particular problem given the syntax of certain functional languages. With anonymous delegates and the lambda operator the syntax in .NET is alot simpler.
Its easier to first consider fn(x,y,z). This could by curried using fn(x,y) giving you a function that only takes one parameter, the z. Whatever needs to be done with x and y alone can be done and stored by a closure that the returned function holds on to.
Now you call the returned function several times with various values for z without having to recompute the part the required x and y.
Edit:
There are effectively two reasons to curry.
Parameter reduction
As Cameron says to convert a function that takes say 2 parameters into a function that only takes 1. The result of calling this curried function with a parameter is the same as calling the original with the 2 parameters.
With Lambdas present in C# this has limited value since these can provide this effect anyway. Although it you are use C# 2 then the Curry function in your question has much greater value.
Staging computation
The other reason to curry is as I stated earlier. To allow complex/expensive operations to be staged and re-used several times when the final parameter(s) are supplied to the curried function.
This type of currying isn't truely possible in C#, it really takes a functional language that can natively curry any of its functions to acheive.
Conclusion
Parameter reduction via the Curry you mention is useful in C# 2 but is considerably de-valued in C# 3 due to Lambdas.
In a sense, curring is a technique to
enable automatic partial application.
More formally, currying is a technique
to turn a function into a function
that accepts one and only one
argument.
In turn, when called, that function
returns another function that accepts
one and only one argument . . . and so
on until the 'original' function is
able to be executed.
from a thread in codingforums
I particularly like the explanation and length at which this is explained on this page.
One example: You have a function compare(criteria1, criteria2, option1, option2, left, right). But when you want to supply the function compare to some method with sorts a list, then compare() must only take two arguments, compare(left, right). With curry you then bind the criteria arguments as you need it for sorting this list, and then finally this highly configurable function presents to the sort algorithm as any other plain compare(left,right).
Detail: .NET delegates employ implicit currying. Each non-static member function of a class has an implicit this reference, still, when you write delegates, you do not need to manually use some currying to bind this to the function. Instead C# cares for the syntactic sugar, automatically binds this, and returns a function which only requires the arguments left.
In C++ boost::bind et al. are used for the same. And as always, in C++ everything is a little bit more explicit (for instance, if you want to pass a instance-member function as a callback, you need to explicitly bind this).
I have this silly example:
Uncurry version:
void print(string name, int age, DateTime dob)
{
Console.Out.WriteLine(name);
Console.Out.WriteLine(age);
Console.Out.WriteLine(dob.ToShortDateString());
Console.Out.WriteLine();
}
Curry Function:
public Func<string, Func<int, Action<DateTime>>> curry(Action<string, int, DateTime> f)
{
return (name) => (age) => (dob) => f(name, age, dob);
}
Usage:
var curriedPrint = curry(print);
curriedPrint("Jaider")(29)(new DateTime(1983, 05, 10)); // Console Displays the values
Have fun!
here's another example of how you might use a Curry function. Depending on some condition (e.g. day of week) you could decide what archive policy to apply before updating a file.
void ArchiveAndUpdate(string[] files)
{
Func<string, bool> archiveCurry1 = (file) =>
Archive1(file, "archiveDir", 30, 20000000, new[] { ".tmp", ".log" });
Func<string, bool> archiveCurry2 = (file) =>
Archive2("netoworkServer", "admin", "nimda", new FileInfo(file));
Func<string, bool> archvieCurry3 = (file) => true;
// backup locally before updating
UpdateFiles(files, archiveCurry1);
// OR backup to network before updating
UpdateFiles(files, archiveCurry2);
// OR do nothing before updating
UpdateFiles(files, archvieCurry3);
}
void UpdateFiles(string[] files, Func<string, bool> archiveCurry)
{
foreach (var file in files)
{
if (archiveCurry(file))
{
// update file //
}
}
}
bool Archive1(string fileName, string archiveDir,
int maxAgeInDays, long maxSize, string[] excludedTypes)
{
// backup to local disk
return true;
}
bool Archive2(string sereverName, string username,
string password, FileInfo fileToArchvie)
{
// backup to network
return true;
}