Reputation: 1940
I'm trying to convert some F# code to C# but I don't understand this particular block:
let GetItems = asyncResult {
let! items = StaticClass.getItems
return
items
|> AsyncSeq.map (fun item ->
fun handleItem -> asyncResult {
let! itemCanBeRemoved = handleItem item|> AsyncResult.mapError HandleItemError
// some code removed for clarity
})
}
My attempt to convert this is:
public static async Task<IEnumerable<T>> GetItems<T>() where T : Item
{
var items = await StaticClass.GetItems();
var tasks = new List<Task>();
foreach (var item in items)
{
bool itemCanBeRemoved;
if (itemCanBeRemoved)
{
// do something
}
else
{
// do something else
}
}
await Task.WhenAll(tasks);
return items;
}
Assuming my conversion is on the right track, I don't understand how the handleItem func is defined and then invoked within its own implementation block. Can someone please explian what handleItem is doing and how it invokes itself?
Upvotes: 0
Views: 170
Reputation: 243051
The key part of your code sample does not actually define a self-calling (i.e. recursive) lambda.
items
|> AsyncSeq.map (fun item ->
fun handleItem -> asyncResult {
let! itemCanBeRemoved = handleItem item|> AsyncResult.mapError HandleItemError
// some code removed for clarity
})
What this does is that it iterates over all items
and generates a new AsyncSeq<T>
where each item is generated from the original one by calling:
fun handleItem -> asyncResult {
let! itemCanBeRemoved = handleItem item|> AsyncResult.mapError HandleItemError
// some code removed for clarity
}
This is not recursive - it defines a lambda that takes handleItem
(presumably a function that can be used to handle the individual items) and returns asyncResult
.
If I understand the code correctly, it would then return something like:
AsyncSeq<(Item -> AsyncResult<Result, Err>) -> AsyncResult<Result, Err>>
This would be an asynchronously generated collection of functions that take function (to process each item) and return result of this processing.
This looks like a very odd thing to do, so I guess this is either badly copied from your actual source code, or it is just very bad F# code.
That said, neither AsyncResult
nor AsyncSeq
have a direct corresponding type in C#, so translating this might be quite hard.
Upvotes: 1
Reputation: 6510
It's hard to tell exactly what the original code is doing without a complete sample, but if I had to guess, I'd say the F# code is likely using a fixed-point combinator to process the items in the list. This can be accomplished in C# by using null-initialized Func
definition to support a recursive-lambda in a LINQ statement.
Func<Item, ValueTuple<Item, bool>> handleItem = null;
handleItem = item => {
var itemCanBeRemoved = handleItem item; // Should do something so that it's not infinitely recursive here
return (item, itemCanBeRemoved);
};
return items.Select(handleItem);
You can reference a similar question here for a more detailed explanation: https://stackoverflow.com/a/61206/1748071
Upvotes: 2