Is this functional code? Dr.T. Reply.
Luca Bolognese -This would be a functional approach:
CountWithPrevious : [‘a] => (a => a => bool) => int // type of the function
CountWithPrevious [] _ = 0
CountWithPrevious [_] _ = 0
CountWithPrevious [prev, val | tail] pred = CountWithPrevious [val | tail] + (pred val prev ? 1 : 0)
Some observations:
_” is used as wildcard argument — matches any value that you don’t need a name for. [ x,y,z | t ] are pattern matching over lists — here x,y and z get bound to the first elements and t is the rest of the list. Both CountWithPrevious and the passed-in pred are curried — they take two arguments but one at a time. The CountWithPrevious function is defined with pattern matching — at runtime it searches through the definitions until one matches. The type declaration is optional — the compiler can figure out the type from the last case of the function. In C# we don’t have pattern matching and currying, and so would probably need a helper function.
public static int CountWithPrevious<T>(IEnumerable<T> en, PredWithPrevious pred) {
IEnumerator<T> rest = en.GetEnumerator();
if (rest.MoveNext()) return Helper(rest.Current,rest,pred);
else return 0;
}
private static int Helper<T>(T prev, IEnumerator<T> rest, PredWithPrevious pred) {
if (rest.MoveNext()) {
T val = rest.Current;
return Helper(val,rest,pred) + (pred(val,prev) ? 1 : 0);
} else return 0;
}
We could simulate local functions with lambdas so that we don’t need to pass pred, prev and T along:
public static int CountWithPrevious<T>(IEnumerable<T> en, PredWithPrevious pred) {
IEnumerator<T> rest = en.GetEnumerator();
Func<T,int> helper = prev => {
if (rest.MoveNext()) {
T val = rest.Current;
return Helper(val) + (pred(val,prev) ? 1 : 0);
} else return 0;
};
if (rest.MoveNext()) return Helper(rest.Current);
else return 0;
}
Tags
- CSHARP
1 Comment
Comments
Charlie Calvert's Community Bl
2007-02-02T02:52:36ZWelcome to the twentieth Community Convergence. I’m Charlie Calvert, the C# Community PM, and this is