I am trying to better understand functional Programming. The example below was provided, this example creates a predicate lambda. Then creates a static method to Count the number of items that pass the predicate conditions.
public Predicate<string> longWords = (x) => x.Length > 10;
public static int Count<T>(T[] array, Predicate<T> predicate, int counter)
{
for (int i = 0; i < array.Length; i++)
{
if (predicate(array[i]))
{
counter++;
}
}
return counter;
}
I wanted to make this solution follow the Referential Transparency principle which states that you can determine the result of applying that function only by looking at the values of its arguments.
Unfortunately longWords doesn't tell me what a long word really means, I need to pass in an argument to longWords telling it the length that makes a function a long word, ie not hardcoding '10'.
Predicates only take in one parameter, and making longWords require Predicate<Tuple<string,int>>, comes with its challenges.
Below is my attempt at coming to a solution, and the two error messages that resulted.
public class BaseFunctions
{
public Predicate<Tuple<string, int>> longWords = (x) => x.Item1.Length > x.Item2;
public static int Count<T>(T[] array, Predicate<T> predicate, int counter)
{
for (int i = 0; i < array.Length; i++)
{
/// error below: Cannot convert from 'T' to 'string'
/// in the example provided predicate(array[i]) worked fine when the predicate had only string type
if (predicate(new Tuple<string, int>(array[i], 10)))
{
counter++;
}
}
return counter;
}
}
and it's usage
BaseFunctions b = new BaseFunctions();
string[] text = ["This is a really long string", "Not 10"];
/// also error below on BaseFunctions.Count 'The type arguments for method BaseFunctions.Count<T>(T[], Predicate<T>, int) cannot be inferred from the usage. Try specifying the arguments explicitly
Console.WriteLine(BaseFunctions.Count(text, b.longWords, 0).ToString());
Console.ReadLine();
I'd do:
public Func<string, int, bool> longWords = (str, number) => str.Length > number;
instead of:
public Predicate<Tuple<string, int>> longWords = (x) => x.Item1.Length > x.Item2;
This is simply because I believe it's easier to work with a function that takes a string and an int then returns a bool as opposed to a predicate that takes a tuple of string and int and returns a bool. plus this version of the tuple type is cumbersome to work with. consider the new tuple types if you're using C#7 and above.
Then change the method signature from:
public static int Count<T>(T[] array, Predicate<T> predicate, int counter)
to:
public static int Count<T>(T[] array, Func<T, int, bool> predicate, int counter)
To accommodate the change of delegate types mentioned above.
Then the if condition needs to be changed from:
if (predicate(new Tuple<string, int>(array[i], 10)))
to:
if (predicate(array[i], 10))
To accommodate the change of delegate types mentioned above.
Also, note that in C# you'll need to define the array like this:
string[] text = { "This is a really long string", "Not 10" };
and not with the [ ] braces.
Now your usage code becomes:
BaseFunctions b = new BaseFunctions();
string[] text = { "This is a really long string", "Not 10" };
Console.WriteLine(BaseFunctions.Count(text, b.longWords, 0).ToString());
Console.ReadLine();
Related
As input i have object that implements IDataRecord(row of some abstract table), so it have indexer, and by giving it some integer i can retrive object of some type. As output my code must get some range of cells in that row as array of given type objects.
So I've written this method(yes, i know, it can be easly converted to extension method, but i don't need this, and also i don't really want to have this method visible outside of my class):
private static T[] GetRange<T>(IDataRecord row, int start, int length)
{
var result = new List<T>();
for (int i = start; i < (start + length); i++)
{
result.Add((T)row[i]);
}
return result.ToArray();
}
It works fine, but this method logic seems like something very common. So, is there any method that can give same(or almost same) result in .NET Framework FCL/BCL?
Use Skip and Take.
var rangeList = result.Skip(start - 1).Take(length);
No, it is not in the BCL.
You should however not create a List<> first and then copy that to the array. Either return the List<> itself (and construct it with the appropriate initial capacity), or create the array immediately like this:
private static T[] GetRange<T>(IDataRecord row, int start, int length)
{
var result = new T[length];
for (int i = 0; i < length; i++)
{
result[i] = (T)row[start + i];
}
return result;
}
Here is an alternative (for all you LINQ lovers):
// NB! Lazy enumeration
private static IEnumerable<T> GetRange<T>(IDataRecord row, int start, int length)
{
return Enumerable.Range(start, length).Select(i => (T)row[i]);
}
We repeat here what was stated in the comments to the question: The interface System.Data.IDataRecord (in System.Data.dll assembly) does not inherit IEnumerable<> or IEnumerable.
If you want to 'TakeARange' you should have a collection as input parameter.
Here you don't have one.
You just have a IDataRecord (eg. a single row) that has an indexer.
You should expose a property called Cells that return the list you work with in the indexer implementation.
Your method should look like this:
private static T[] TakeRange<T>(IEnumerable cells, int start, int length)
{
return cells.Skip(start - 1).Take(length)
}
Well.. Seem's like there is no such method in FCL/BCL
I am looking for a way to chain several delegates so the result from one becomes the input of the next. I am trying to use this in equation solving program where portions are done by different methods. The idea is that when you are building the equation the program adds the delegates and chains them in a particular order, so it can be solved properly. If there is a better way to approach the problem please share.
This might help:
public static Func<T1, TResult> Compose<T1, T2, TResult>(Func<T1, T2> innerFunc, Func<T2, TResult> outerFunc) {
return arg => outerFunc(innerFunc(arg));
}
This performs function composition, running innerFunc and passing the result to outerFunc when the initial argument is supplied:
Func<double, double> floor = Math.Floor;
Func<double, int> convertToInt = Convert.ToInt32;
Func<double, int> floorAndConvertToInt = Compose(floor, convertToInt);
int result = floorAndConvertToInt(5.62);
Func<double, int> floorThenConvertThenAddTen = Compose(floorAndConvertToInt, i => i + 10);
int result2 = floorThenConvertThenAddTen(64.142);
Yes this is possible - you need to ensure that the return type of the delegate is one that is the parameter type of the delegate being invoked.
A lot of LINQ is built this ways, though you may want to take a look at expressions.
The type of API you are describing is called a Fluent API. Take a look at the preceeding article for a good tutorial.
With regard to delegate chaining, take a look at the LINQ extension methods in .NET 3.5, in particular how lambda functions (delegates) passed to a function result in an IEnumerable result which can then be chained with another extension method + lambda.
In your specific case you might need to create a class called a Functor to accept a delegate and return another Functor which too can be operated on by delegates.
Best regards,
using GetInvocationlist you can achieve this.
Delegate[] chain = chained.GetInvocationList();
int res = 10;
for( int i = 0; i < chain.Length; i++ )
{
//Call chain[i]
res = chain[i](res);
}
I have been working on a similar problem myself which involved invoking a sequence of delegates and passing the output of one delegate to the next (and so on...) so thought you might be interested to see the code I developed as a proof-of-concept:
static class Program
{
private static IList<Func<int, int>> delegateList =
new List<Func<int, int>>()
{
AddOne, AddOne, AddOne, AddOne, AddOne,
AddOne, AddOne, AddOne, AddOne, AddOne,
};
static void Main(string[] args)
{
int number = 12;
Console.WriteLine("Starting number: {0}", number);
Console.WriteLine("Ending number: {0}",
delegateList.InvokeChainDelegates(number));
Console.ReadLine();
}
public static int AddOne(int num) { return num + 1; }
public static T InvokeChainDelegates<T>(this IEnumerable<Func<T, T>> source,
T startValue)
{
T result = startValue;
foreach (Func<T, T> function in source)
{
result = function(result);
}
return result;
}
}
The sequence has to contain delegates of the same type so is not as powerful as the already accepted answer but with a few tweaks, both bits of code could be combined to provide a powerful solution.
I ran into what was to me an unexpected result when testing a simple ForEach extension method.
ForEach method
public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
if (action == null) throw new ArgumentNullException("action");
foreach (T element in list)
{
action(element);
}
}
Test method
[TestMethod]
public void BasicForEachTest()
{
int[] numbers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
numbers.ForEach(num =>
{
num = 0;
});
Assert.AreEqual(0, numbers.Sum());
}
Why would numbers.Sum() be equal to 55 and not 0?
num is the copy of the value of the current element you are iterating over. So you are just changing the copy.
What you do is basically this:
foreach(int num in numbers)
{
num = 0;
}
Surely you do not expect this to change the content of the array?
Edit: What you want is this:
for (int i in numbers.Length)
{
numbers[i] = 0;
}
In your specific case you could maintain an index in your ForEach extension method and pass that as second argument to the action and then use it like this:
numbers.ForEachWithIndex((num, index) => numbers[index] = 0);
However in general: Creating Linq style extension methods which modify the collection they are applied to are bad style (IMO). If you write an extension method which cannot be applied to an IEnumerable<T> you should really think hard about it if you really need it (especially when you write with the intention of modifying the collection). You have not much to gain but much to loose (like unexpected side effects). I'm sure there are exceptions but I stick to that rule and it has served me well.
Because num is a copy.
It's as if you were doing this:
int i = numbers[0];
i = 0;
You wouldn't expect that to change numbers[0], would you?
Because int is a value type and is passed to your extension method as a value parameter. Thus a copy of numbers is passed to your ForEach method. The values stored in the numbers array that is initialized in the BasicForEachTest method are never modified.
Check this article by Jon Skeet to read more on value types and value parameters.
I am not claiming that the code in this answer is useful, but (it works and) I think it illustrates what you need in order to make your approach work. The argument must be marked ref. The BCL does not have a delegate type with ref, so just write your own (not inside any class):
public delegate void MyActionRef<T>(ref T arg);
With that, your method becomes:
public static void ForEach2<T>(this T[] list, MyActionRef<T> actionRef)
{
if (actionRef == null)
throw new ArgumentNullException("actionRef");
for (int idx = 0; idx < list.Length; idx++)
{
actionRef(ref list[idx]);
}
}
Now, remember to use the ref keyword in your test method:
numbers.ForEach2((ref int num) =>
{
num = 0;
});
This works because it is OK to pass an array entry ByRef (ref).
If you want to extend IList<> instead, you have to do:
public static void ForEach3<T>(this IList<T> list, MyActionRef<T> actionRef)
{
if (actionRef == null)
throw new ArgumentNullException("actionRef");
for (int idx = 0; idx < list.Count; idx++)
{
var temp = list[idx];
actionRef(ref temp);
list[idx] = temp;
}
}
Hope this helps your understanding.
Note: I had to use for loops. In C#, in foreach (var x in Yyyy) { /* ... */ }, it is not allowed to assign to x (which includes passing x ByRef (with ref or out)) inside the loop body.
I have recently moved to .net 3.0 (windows forms, C#). I want to know more about predicates and lambda expressions. Where should we use them? Do they improve performance? and how do they work internally. Thanks.
If you search Stack Overflow you'll find about a thousand answers explaining what they're for. In short - a lambda is a way of writing an anonymous method at the point where you want to pass it to another method. Technically the same as the delegate syntax for an anonymous method, although with added powers of type inference so you don't need to state the parameter types. A predicate is a method that accepts some value and returns a bool - an example would be the argument to Where.
A lambda that doesn't refer to any external variables gets turned into a private static method with a made-up name. If it refers to instance members of the enclosing class, it becomes an instance method. If it refers to local variables, those variables get "hoisted" into being fields of a compiler-generated class that is allocated when the enclosing method starts running, and the lambda's body becomes a method in that new class.
As for performance, they don't make that much difference. They involve the creation of temporary objects, but I find that these are collected extremely efficiently by the GC.
If you want to study the different versions of C# and how they different .My suggestion is read the book C.Sharp.in.Depth by jon skeet . This will give you the better understanding of new versions
Do they improve performance? and how
do they work internally. Thanks.
For the most part, you'll never notice the performance hit. However, there are some pathological cases which will kill performance, namely overzealous use of fixed point combinators.
Its a well-known trick that we can use the Y-combinator to write recursive lambda functions, however consider the following code:
using System;
using System.Diagnostics;
namespace YCombinator
{
class Program
{
static Func<T, U> y<T, U>(Func<Func<T, U>, Func<T, U>> f)
{
return f(x => y<T, U>(f)(x));
}
static int fibIter(int n)
{
int fib0 = 0, fib1 = 1;
for (int i = 1; i <= n; i++)
{
int tmp = fib0;
fib0 = fib1;
fib1 = tmp + fib1;
}
return fib0;
}
static Func<int, int> fibCombinator()
{
return y<int, int>(f => n =>
{
switch (n)
{
case 0: return 0;
case 1: return 1;
default: return f(n - 1) + f(n - 2);
}
});
}
static int fibRecursive(int n)
{
switch (n)
{
case 0: return 0;
case 1: return 1;
default: return fibRecursive(n - 1) + fibRecursive(n - 2);
}
}
static void Benchmark(string msg, int iterations, Func<int, int> f)
{
int[] testCases = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20 };
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i <= iterations; i++)
{
foreach (int n in testCases)
{
f(n);
}
}
watch.Stop();
Console.WriteLine("{0}: {1}", msg, watch.Elapsed.TotalMilliseconds);
}
static void Main(string[] args)
{
int iterations = 10000;
Benchmark("fibIter", iterations, fibIter);
Benchmark("fibCombinator", iterations, fibCombinator());
Benchmark("fibRecursive", iterations, fibRecursive);
Console.ReadKey(true);
}
}
}
This program prints out:
fibIter: 14.8074
fibCombinator: 61775.1485
fibRecursive: 2591.2444
fibCombinator and fibRecursive are functionally equivalent and have the same computational complexity, but fibCombinator is a full 4100x slower due to all of the intermediate object allocations.
I want to write a method which can take an arbitrary array of a numeric type and return the sum of all the elements between startIndex and endIndex. This is what I have:
private static T SumArrayRange<T>(T[] scores, int startIndex, int endIndex)
{
T score = 0;
for (int i = startIndex; i <= endIndex; i++)
{
score += scores[i];
}
return score;
}
But the compilation fails with these 2 errors.
Cannot implicitly convert type 'int'
to 'T'.
Operator '+=' cannot be
applied to operands of type 'T' and
'T'
Is there any way I can force T to be only one of the numeric types (long, double etc.)? Or is their a more elegant way of solving this?
No, there's no way to constrain generic type parameters to use operators, and there are no good workarounds for that, either. A proper one would be an interface such as INumeric or IArithmetic with methods such as Add, Subtract etc, implemented by all primitive types such as int and long. There is a 5-year old feature request for that in MS Connect, which is still Active. The latest word on that is:
Unfortunately, we've had to cut our plans to solve this problem in the .NET Framework 4.0.
Until then, you are relegated to either:
using Reflection yourself - messy and very slow
using any of the existing wrappers that will use Reflection for you (e.g. Microsoft.VisualBasic.CompilerServices.Operators class, with methods such as AddObject, SubtractObject etc which use reflection and implement VB semantics for the corresponding operators) - easy to use, but still very slow
hardcoding types you want to handle (i.e. no support for overloaded arithmetic operators on user-defined types), and using a giant if (x is int) ... else if (x is double) ... statement.
Another approach is to use the LINQ tools that are already available, rather than writing your own. For example:
var mySum = myCollection.Skip(startIndex).Take(count).Sum();
Since the Sum extension method exists for all of the built-in numeric types, you don't have to worry about writing your own. Of course, this won't work if your code's "myCollection" variable is already of a generic collection type.
This approach works pretty well:
http://www.codeproject.com/KB/cs/genericnumerics.aspx
The solution is in dynamic keyword.
T score = default(T)
for (int i = startIndex; i <= endIndex; i++)
{
score += (dynamic)scores[i];
}
return score;
It is a concept named late binding.
There is no type to which you can constrain T that will allow the += operator to work. This is because .NET does not have a type that means numeric.
This is because T could be any type. If T was a HttpWebRequest could you assign 0 to it, or could you use the += operator on it?
You can get around the first error by using
T score = default(T);
I'm not sure how you'd deal with the second because you'd have to constrain T to be types that implement a += operator.
Generic constraints are the only possiblilty I can think of. But, being drunk, I can't exactly test this!
I'm perhaps being stupid, but won't int.Parse() fix this problem?
Here my variant
uses binary operator "add" of type T as default,
but offers ability to customize the add function for some specified types, and use the default binary add only for the rest
(throwing an exception at runtime if binary add isn't defined for type T).
private static Func<T, T, T> CreateAdd<T>()
{
Func<T, T, T> addMethod = null;
Expression<Func<T, T, T>> addExpr = null;
if (typeof(T) == typeof(string))
{
//addExpr = (Expression<Func<T, T, T>>)((a, b) => ((T)(object)((string)(object)a + (string)(object)b)));
//addMethod = addExpr.Compile();
addMethod = (a, b) => {
string aa = (string)(object)a;
string bb = (string)(object)b;
double da;
double db;
double.TryParse(aa, out da);
double.TryParse(bb, out db);
double c = da + db;
string res = c.ToString();
return (T)(object)res;
}; // End Delegate addMethod
}
else
{
ParameterExpression lhs = Expression.Parameter(typeof(T), "lhs");
ParameterExpression rhs = Expression.Parameter(typeof(T), "rhs");
addExpr = Expression<Func<T, T, T>>.Lambda<Func<T, T, T>>(
Expression.Add(lhs, rhs),
new ParameterExpression[] { lhs, rhs }
);
addMethod = addExpr.Compile();
}
return addMethod;
}
// MvcTools.Aggregate.Functions.Sum<T>(vals);
public static T Sum<T>(params T[] vals)
{
T total = default(T);
//Enumerable.Aggregate(vals, delegate(T left, T right) { return left + right; });
Func<T, T, T> addMethod = CreateAdd<T>();
foreach (T val in vals)
{
total = addMethod(total, val);
}
return total;
} // End Function Sum
Example:
int[] vals = new int[] { 1, 2, 3, 4, 5 };
int sum = MvcTools.Aggregate.Functions.Sum<int>(vals);
double[] dvals = new double[] { 1, 2, 3, 4, 5 };
double dsum = MvcTools.Aggregate.Functions.Sum<double>(dvals);
string[] strs = new string[] { "1", "2", "3", "4", "5" };
string str = MvcTools.Aggregate.Functions.Sum<string>(strs);
output: 15, 15.0, "15"