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).
Related
I came across the following piece of code in the Sprache repository :
Parser<string> identifier =
from leading in Parse.WhiteSpace.Many()
from first in Parse.Letter.Once().Text()
from rest in Parse.LetterOrDigit.Many().Text()
from trailing in Parse.WhiteSpace.Many()
select first + rest;
var id = identifier.Parse(" abc123 ");
I see a contradiction here: the from clause docs say the source (Parse.WhiteSpace.Many() or Parse.Letter.Once().Text() in our case) must be IEnumerable:
The data source referenced in the from clause must have a type of IEnumerable, IEnumerable<T>, or a derived type such as IQueryable<T>
But it isn't and the compiler says that's fine!
I thought there is some implicit cast to IEnumerable, but there isn't: Parse.WhiteSpace.Many() returns Parser<IEnumerable<T>> and Parse.Letter.Once().Text() returns Parser<string> (types are not IEnumerable).
1st question: Why does the compiler allow this code?
Also, the final expression select first + rest doesn't take into account leading and trailing variables, but the final result identifier, for sure, uses them inside.
2nd question: By what rule\mechanism leading and trailing variables were added to the identifier?
P.S.
It'd be great if someone shared an all-encompassing doc about internal work of LINQ query syntax. I've found nothing on this topic.
After like five minutes of looking at the code I have observed:
parser is a delegate that returns an intermediate result
public delegate IResult<T> Parser<out T>(IInput input);
there are linq compliant methods declared that allow linq syntax like:
public static Parser<U> Select<T, U>(this Parser<T> parser, Func<T, U> convert)
{
if (parser == null) throw new ArgumentNullException(nameof(parser));
if (convert == null) throw new ArgumentNullException(nameof(convert));
return parser.Then(t => Return(convert(t)));
}
https://github.com/sprache/Sprache/blob/develop/src/Sprache/Parse.cs#L357
It is not true that IEnumerable interface is required for the syntax from x in set to work you just require particular extension method with correct name that accepts correct set of parameters. So the above makes select valid. Here you have where method
public static Parser<T> Where<T>(this Parser<T> parser, Func<T, bool> predicate)
{
if (parser == null) throw new ArgumentNullException(nameof(parser));
if (predicate == null) throw new ArgumentNullException(nameof(predicate));
return i => parser(i).IfSuccess(s =>
predicate(s.Value) ? s : Result.Failure<T>(i,
$"Unexpected {s.Value}.",
new string[0]));
}
https://github.com/sprache/Sprache/blob/develop/src/Sprache/Parse.cs#L614
and so on.
This is separate implementation of the linq abstraction that has nothing to do with collections it is about parsing text. It produces a nested chain of delegates that process given string to verify if it confirms to particular gramma and returns structure that describes parsed text.
that answers first question. For the second you need to follow the code: all from x in set except the first one map to SelectMany function:
public static Parser<V> SelectMany<T, U, V>(
this Parser<T> parser,
Func<T, Parser<U>> selector,
Func<T, U, V> projector)
{
if (parser == null) throw new ArgumentNullException(nameof(parser));
if (selector == null) throw new ArgumentNullException(nameof(selector));
if (projector == null) throw new ArgumentNullException(nameof(projector));
return parser.Then(t => selector(t).Select(u => projector(t, u)));
}
https://github.com/sprache/Sprache/blob/develop/src/Sprache/Parse.cs#L635
and Then method
https://github.com/sprache/Sprache/blob/develop/src/Sprache/Parse.cs#L241
there you will see that if first succeeds (leading white spaces where matched) only than second (the single letter parser) is applied on the remainder of the string. So Again it is not a collection processing its a chain of events that lead to parsing the string.
Trying to build a formatting delegate/function. It's mainly for printing exercise results.
I am trying to access the result of a argument but I think my understanding of delegates is still kind of bad. The method is invokable in the block itself but I would like the result, currently it prints the result definition.
System.Func2[ConsoleApp1.LoanQueries,System.Collections.Generic.IEnumerable1[System.Decimal]]
Below is the code that will create to result to parse, the parsing method and a code snippet that I based my code on.
My questions are:
Is this possible or am I breaking some rules?(trying to use expressions/functional)
Is it possible to declare just a delegate instead of the function(This would probably involve formatting every time instead of the function.)
Create data to format
// Method bodied expression
public IEnumerable<decimal> LoanQueryBodied =>
from amount in LoanAmounts
where amount % 2 == 0
orderby amount ascending
select amount;
// Query expression:
public IEnumerable<decimal> LoanQueryExpression () =>
LoanAmounts
.Where(a => a % 2 == 0)
.OrderBy(r => r);
Method for data and final formatting
public static void FormatLoans<TObject>(
Func<TObject> instance,
Func<TObject, IEnumerable<decimal>> function)
{
// This is the function object but should be IEnumerable<decimal> result passed down.
// Just like TObject is passed , but how?
Console.WriteLine(string.Join(" - ",function));
}
Use method
LoanQueries.FormatLoans<LoanQueries>(() =>
new LoanQueries()
, inst => inst.LoanQueryBodied);
LoanQueries.FormatLoans<LoanQueries>(() =>
new LoanQueries()
, inst => inst.LoanQueryExpression());
Code that I based it loosely on
public static class Disposable
{
public static TResult Using<TDisposable, TResult>(
Func<TDisposable> factory,
Func<TDisposable, TResult> map)
where TDisposable : IDisposable
{
using (var disposable = factory())
{
return map(disposable);
}
}
}
Example invoked
var time= Disposable
.Using(
() => new WebClient(),
client => XDocument.Parse(client.DownloadString("http://time.gov/actualtime.cgi")))
.Root
.Attribute("time")
.Value;
I would like to chain my method like this but if this is not possible or bad practice I would also like to know.
You need to call function and instance using ():
Console.WriteLine(string.Join(" - ",function(instance())));
And apparently you want to return the string, rather than printing it, to allow chaining, so:
public static string FormatLoans<TObject>(
Func<TObject> instance,
Func<TObject, IEnumerable<decimal>> function) =>
string.Join(" - ",function(instance()));
However, I think you are really over-complicating/over-generalising this. Your method is not nearly as general as the Disposable.Using method you showed. Your method could just be declared like this:
public static string FormatLoans(IEnumerable<decimal> loans) =>
string.Join(" - ", loans);
Callers:
LoanQueries.FormatLoans(new LoanQueries().LoanQueryBodied)
LoanQueries.FormatLoans(new LoanQueries().LoanQueryExpression)
Disposable.Using uses delegates because it is trying to recreate the using statement. The second argument must be evaluated inside the using statement, so that any exceptions thrown lead to the disposal of the IDisposable, which is why it has to be wrapped up in a delegate. If not, the second argument would be evaluated before the Using method runs, and that misses the whole point.
However, your method does not have special requirements like that, so you don't need delegates.
I am reading C# AsEnumerable:
"The IEnumerable interface is a generic interface. This means it
defines a template that types can implement for looping. The
AsEnumerable method, a generic method, allows you to cast a specific
type to its IEnumerable equivalent"
Further on, a code example:
using System;
using System.Linq;
class Program
{
static void Main()
{
// Create an array type.
int[] array = new int[2];
array[0] = 5;
array[1] = 6;
// Call AsEnumerable method.
var query = array.AsEnumerable();
foreach (var element in query)
{
Console.WriteLine(element);
}
}
}
Sounds like I need to convert an array to an IEnumerable type object to use looping (foreach?).
But applying foreach directly to an array yields exactly the same results:
using System;
//using System.Linq;
class Program
{
static void Main()
{
// Create an array type.
int[] array = new int[2];
array[0] = 5;
array[1] = 6;
// Call AsEnumerable method.
//var query = array.AsEnumerable();
foreach (var element in array)
{
Console.WriteLine(element);
}
}
}
So, the entire webpage with an explanation of AsEnumerable() method is void for me.
What did I miss?
The example is bad and it should feel bad. Here is a better, if somewhat contrived example:
If I have an extension method defined on the, let's say, the array type, like this:
public static class ArrayExtension {
public static bool Any<T>(this T[] source, Func<T,bool> predicate)
{
Console.WriteLine("Undesirable side behaviour");
SomeResourceIntensiveOperation();
Console.WriteLine("Inefficient implementation");
return source.Where(predicate).Count() != 0;
}
}
and I do
int[] nums = new []{1,2,3,4,5};
nums.Any(n=> n % 2 == 0);
If will execute and run my implementation, even if i do not need that. By doing
nums.AsEnumerable().Any(n => n % 2 == 0);
it will call the default implementation.
The real benefit is when you are using IQueryable implementations (e.g. LINQ-to-SQL), because, for example, the Where for IEnumerable is defined as
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
but the IQueryable.Where is defined with
public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate)
When the IQueryable behaviour is undesireable one can call the AsEnumerable() to force the IEnumerable behaviour.
From MSDN
The AsEnumerable<TSource>(IEnumerable<TSource>) method has no effect other than to change the compile-time type of source from a type that implements IEnumerable<T> to IEnumerable<T> itself.
AsEnumerable<TSource>(IEnumerable<TSource>) can be used to choose between query implementations when a sequence implements IEnumerable<T> but also has a different set of public query methods available. For example, given a generic class Table that implements IEnumerable<T> and has its own methods such as Where, Select, and SelectMany, a call to Where would invoke the public Where method of Table. A Table type that represents a database table could have a Where method that takes the predicate argument as an expression tree and converts the tree to SQL for remote execution. If remote execution is not desired, for example because the predicate invokes a local method, the AsEnumerable<TSource> method can be used to hide the custom methods and instead make the standard query operators available.
It makes no sense in YOUR example logically (i.e. from array). I would assume the first code has been written by a beginner, or - more down - an example.
It does make sense in the sense of LINQ as "AsEnumerable" triggers the evaluation of the query and depending on the ORM That can mean freeing up a database connection for a reuse within the loop.
THAT SAID:
You read too much into examples. In an example, code is there not to be "good" but to show a point. In this case it may make sense to DEMONSTRATE the use of AsEnumerable - and an Array is the fastest enumerable object to initialize (in terms of lines of code), to keep the example short. Examples point out specific things, they are not "good code" for anything.
This is just another example. Suppose I have this method:
static void MyMeth(int[] numbers)
{
var query = numbers.Reverse(); // works fine, calls Linq extension
// ... use query ...
}
Then I decide to change numbers into a List<int> instead, and try:
static void MyMeth(List<int> numbers)
{
var query = numbers.Reverse(); // will not compile!
// ... use query ...
}
The problem here is that the List<> class has another method which is also called Reverse. That method returns void (because it modifies the original List<> in-place). I don't want that. One solution would be to upcast numbers explicitly:
static void MyMeth(List<int> numbers)
{
var query = ((IEnumerable<int>)numbers).Reverse(); // fine; Linq
// ... use query ...
}
But another solution would be AsEnumerable<>, so:
static void MyMeth(List<int> numbers)
{
var query = numbers.AsEnumerable().Reverse(); // fine too; Linq
// ... use query ...
}
Conclusion: The purpose of AsEnumerable method is to "forget" methods on the specialized type that happen to "hide" the extension methods on the general type IEnumerable<>. This can be incredibly important in the case where the "specialized" type is/inherits IQueryable<> where there are (extension) methods Where, Select and so on which do something different (namely ingest the lambda as an expression tree, analyze it, and "translate" it into SQL or something) than do Where, Select etc. on IEnumerable<>.
I'm looking to make certain functions as generic as possible.
In my MVC applications I have to convert a number of complex IEnumerable objects to SelectLists for dropdown display etc.
At first I created a static List class with conversion methods for each complex object. This amounted to a lot of code. I next started using linq statements to do the conversion:
var list = (from o in SessionTypes select new SelectListItem { Value = o.ID.ToString(), Text = o.Title }).ToList();
but again, this still was a lot of code when taken over many such conversions.
I finally settled something similar to:
public IEnumerable<SelectListItem> ToSelectList<T>(IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text)
{
return enumerable.Select(f => new SelectListItem()
{
Value = value(f),
Text = text(f),
});
}
and to make it easier to use, I made it an extension method:
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text)
{
return enumerable.Select(f => new SelectListItem()
{
Value = value(f),
Text = text(f),
});
}
So now, all I have to do is:
var list = SessionTypes.ToSelectList(o => o.ID.ToString(), o => o.Title) as List<SelectListItem>;
I have similar methods such as .ToDictionary too.
Is this overusing Extension methods? I worry that I'm hiding too much code away in extension methods which might be distorting my models, would it be better to use linq conversions for transparency?
You can bind IDictionary<,> to the DropDownList DataSource directly, in WebForms you need to specify mappings like DataValueField="Key" and DataTextField="Value". Considering that why not just use LINQ ToDictionary() method?
dropDownList.DataValueField = "Key";
dropDownList.DataTextField = "Value";
dropDownList.DataSource =
SessionTypes.ToDictionary(k => k.ID.ToString(),
v => v.Title);
This guideline is from C# in Depth :
"An extension method is reasonably valid if it's applicable to all
instances of the extended type. If it's only appropriate in certain
situations, then make it clear that the method is not part of type by
leaving it as a "normal" static method".
As long as you are okey in exposing this extension method on all instances of type IEnumerable, then you are good to go.
On a lighter note, I would rather call the extension method as ToSelectListItem, rather than ToSelectList, to make it clear for the end user. Again this is my personal preference.
This is a perfectly acceptable usage of extension methods.
So long as they are descriptively named and do what they say you should not have problems.
Given a list of Func<string, string>, is it possible to write a statement that iterates through the list and returns the result like so:
string result = f1(f2(f..(input));
I have the following code (that works), but I'm not satisfied with the temporary variable.
public static string WrapEachElementWith<T>
( this IEnumerable<T> target,
params Func<string, string>[] func )
{
string result = string.Empty;
target.Each(s =>
{
var tmp = s.ToString();
func.Reverse().Each(x => tmp = x(tmp));
result += tmp;
});
return result;
}
How to simplify / refactor?
UPDATE:
I should have provided more background. I'm playing around with Functional programming in c# after seeing higher order JavaScript session and John's abusive c# session at Oredev.
The aim is to generate html.
var TABLE = WrapWith("TABLE");
var TR = WrapWith("TR");
var TD = WrapWith("TD");
const string expected = "<TABLE><TR><TD>1</TD></TR><TR><TD>2</TD></TR></TABLE>";
var result = TABLE(stringArray.WrapEachWith(TR, TD));
result.ShouldEqual(expected);
static Func<String, String> WrapWith(string element)
{
var startTag = '<' + element + '>';
var endTag = "</" + element + '>';
return s => startTag + s + endTag;
}
It looks to me like you're doing four things:
Converting each item to a string
Applying the functions in turn
Applying that composite function to each string in a sequence
Joining the results together (inefficiently)
I would separate out those four aspects - in particular, string.Join works well enough for the fourth part, and Enumerable.Select does the third one.
I would also avoid reversing the order of the operations - I would expect the first operation I specify to be the first one applied, personally.
So, I would rewrite this method to return a Func<string, string> which could then be used with Select and Join. For example:
public static Func<string, string> Compose(params Func<string, string> funcs)
{
return input => {
string current = input;
foreach (var func in funcs)
{
current = func(current);
}
return current;
};
}
You could, of course, make this generic itself, with a signature of:
public static Func<T, T> Compose(params Func<T, T> funcs)
You would then call it with something like:
var composite = Compose<string>(FirstFunction, SecondFunction, ThirdFunction);
var query = string.Join("", items.Select(x => x.ToString())
.Select(composite));
public static string WrapEachElementWith
( string input,
params Func<string, string>[] func )
{
foreach (var f in func.Reverse())
input = f(input);
return input;
}
Not sure why you need template parameter, all the functions map string to string, right?
Note that there's no Each extension of IEnumerable, so you'll have to resort to foreach or write your own Each.
Edit:
your code actually applies this function to all the values from the list, so the actual code would be something like:
public static string F<T>
( this IEnumerable<T> target,
params Func<string, string>[] func )
{
target.Select(item => WrapEachElementWith(item.ToString(), func))
.Aggregate((sum, cur) => sum + cur);
}
As #Jon already mentioned, summing up this way is pretty inefficient, therefore you perhaps would like to put it this way:
string.Join("", target.Select(
item => WrapEachElementWith(item.ToString(), func)));
This guy wrote an entire ray tracer using LINQ. I haven't looked at his code that closely, but he describes using a technique called a "Y-combinator" to create recursion in a LINQ statement. He references this blog posting, which gives a detailed description of these recursive lambda expressions.
I don't know if that's quite what you're looking for, but it might get you off on the right footing.