I think my mind is exploding trying to figure out Funcs... If this makes no sense, I apologize, right now it make sense to me but its been a long day already ....
1) Assuming you are given a func which takes in T and outputs a string:
Func<T, string>
Can you transform that into a func that take in a T and returns a bool based on some logic (in this case if the returned string is empty (String.IsNullOrWhiteSpace)?
Func<T, bool>
2) Can you do the same thing if you are given an
Expression<Func<T, string>>
and need to convert it to a
Func<T, bool>
that returns true/false based on if the returned string is empty (String.IsNullOrWhiteSpace)?
Thanks
for the first part you can even make some "higher"-order function:
Func<A,C> MapFun<A,B,C>(Func<A,B> input, Func<B,C> transf)
{
return a => transf(input(a));
}
use with
Func <T,string> test = ...
var result = MapFun(test, String.IsNullOrWhiteSpace);
(I hope C# type type inference is working here)
If you define this as extension on Func it gets even easier:
public static class FuncExtension
{
public static Func<A,C> ComposeWith<A,B,C>(this Func<A,B> input, Func<B,C> f)
{
return a => f(input(a));
}
}
here is a very simple test:
Func<int, string> test = i => i.ToString();
var result = test.ComposeWith(string.IsNullOrEmpty);
For the second one: I think you can compile the expression into a "real" Func and then use the above code. see MSDN Docs on Expression.Compile
PS: renamed the function to better match it's intend (it's function composition)
Could you not define it as a separate delegate:
Func<T, string> func1 = t => t.ToString();
Func<T, bool> func2 = t => string.IsNullOrEmpty(func1(t));
For the first part the technique is known as function composition i.e you compose 2 functions to create a new function.
In your case you have a function Func<T,String>
and another function (like string empty or null) which is of type Func<string,bool>
, using function composition you can compose these two functions to create a new function of type Func<T,Bool>
Most functional programming language have this composition of function already defined in their standard library or in the language itself. But it is no tough to create one for your language if the language supports functions as first class values.
In C# you can use the below function which will allow you to compose functions:
public static Func<X,Z> Compose<X,Y,Z>(Func<X,Y> a, Func<Y,Z> b)
{
return (v) => b(a(v));
}
To 1: Yes (You can also parametrize bool and string):
Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map)
{
return x => map(source(x));
}
To 2: Yes, but you need to compile the expression first:
Func<T, bool> Compose<T>(Expression<Func<T, string>> source, Func<string, bool> map)
{
return x => compose(source.Compile(), map)
}
.Compile
will compile the expression into a dynamic CLR method that you can invoke with the returned delegate.
You can use this code like this:
Func<int, string> ts = i => i.ToString();
var result = Compose(ts, string.IsNullOrEmpty);
By the way, in this case you should really write a higher-order function. What you are doing here (algebraically) is composing monoids. Remember function composition? f . g := f(g(x))
is what you are doing here.
Think of source as g:A->B
and map as f:B->C
(where A,B and C are sets) so the result of f . g
is h:A->C
. By the way, the .
operator is often build into functional programming languages, such as Haskell and achieves the same thing as your compose
function (but with cleaner syntax).
来源:https://stackoverflow.com/questions/7138182/convert-funct-string-to-funct-bool