Skip to content

Commit

Permalink
Prepare article for publication
Browse files Browse the repository at this point in the history
  • Loading branch information
ploeh committed Nov 18, 2024
1 parent 2511f50 commit d680d85
Showing 1 changed file with 7 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
layout: post
title: "Collecting and handling result values"
description: "The answer is traverse. It's always traverse."
date: 2024-10-24 9:25 UTC
date: 2024-11-18 7:39 UTC
tags: [Functional Programming]
---
{% include JB/setup %}
Expand All @@ -12,13 +12,13 @@
<em>{{ page.description }}</em>
</p>
<p>
I recently came across <a href="https://stackoverflow.com/q/79112836/126014">a Stack Overflow question</a> about collecting and handling <a href="https://en.wikipedia.org/wiki/Tagged_union">sum types</a> (AKA discriminated unions or, in this case, result types). While the question was tagged <em>functional-programming</em>, the overall structure of the code was so imperative with so much interleaved <a href="https://en.wikipedia.org/wiki/Input/output">I/O</a> that it hardly <a href="/2018/11/19/functional-architecture-a-definition">qualified as functional architecture</a>.
I recently came across <a href="https://stackoverflow.com/q/79112836/126014">a Stack Overflow question</a> about collecting and handling <a href="https://en.wikipedia.org/wiki/Tagged_union">sum types</a> (AKA discriminated unions or, in this case, result types). While the question was tagged <em>functional-programming</em>, the overall structure of the code was so imperative, with so much interleaved <a href="https://en.wikipedia.org/wiki/Input/output">I/O</a>, that it hardly <a href="/2018/11/19/functional-architecture-a-definition">qualified as functional architecture</a>.
</p>
<p>
Instead, I gave <a href="https://stackoverflow.com/a/79112992/126014">an answer which involved a minimal change to the code</a>. Subsequently, the original poster asked to see a more functional version of the code. That's a bit too large a task for a Stack Overflow answer, I think, so I'll do it here on the blog instead.
</p>
<p>
Further comments and discussion on the original post reveal that the poster is interested in two alternatives. I'll start with the alternative that's only discussed, but not shown in the question. The motivation for that is that this variation is easier to implement than the other one, and I consider it pedagogical to start with the simplest case.
Further comments and discussion on the original post reveal that the poster is interested in two alternatives. I'll start with the alternative that's only discussed, but not shown, in the question. The motivation for this ordering is that this variation is easier to implement than the other one, and I consider it pedagogical to start with the simplest case.
</p>
<p>
I'll do that in this article, and then follow up with another article that covers the short-circuiting case.
Expand Down Expand Up @@ -83,7 +83,7 @@ <h3 id="c4e1b030e919464aa22ade11a511414f">
The <code>results</code> object is a sequence of tasks. If we consider <a href="/2020/07/27/task-asynchronous-programming-as-an-io-surrogate">Task as a surrogate for IO</a>, each task should be considered impure, as it's either non-deterministic, has side effects, or both. This means that we can't pass <code>results</code> to a pure function, and that frustrates the ambition to structure the code as an Impureim Sandwich.
</p>
<p>
This is one of the most common problems in functional programming, and the answer is usually: Use a <a href="">traversal</a>.
This is one of the most common problems in functional programming, and the answer is usually: Use a <a href="/2024/11/11/traversals">traversal</a>.
</p>
<p>
<pre><span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">OneOf</span>&lt;<span style="color:#2b91af;">ShoppingListItem</span>,&nbsp;<span style="color:#2b91af;">NotFound</span>&lt;<span style="color:#2b91af;">ShoppingListItem</span>&gt;,&nbsp;<span style="color:#2b91af;">Error</span>&gt;&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">results</span>&nbsp;=
Expand Down Expand Up @@ -127,7 +127,7 @@ <h3 id="8f0e6fb0f34047ed99c59f6140a2b08f">
It's also possible to inline the <code>seed</code> value, but here I defined it in a separate expression in an attempt at making the code a little more readable. I don't know if I succeeded, because regardless of where it goes, it's hardly <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatic</a> to break tuple initialization over multiple lines. I had to, though, because otherwise the code would run <a href="/2019/11/04/the-80-24-rule">too far to the right</a>.
</p>
<p>
The lambda expression handles each result in <code>results</code> and uses <code>Match</code> to append the value to its proper 'bucket'. The <code>result</code> is a tuple with the three collections.
The lambda expression handles each <code>result</code> in <code>results</code> and uses <code>Match</code> to append the value to its proper 'bucket'. The outer <code>result</code> is a tuple of the three collections.
</p>
<h3 id="035012be047e431d8904686ec9915b8f">
Saving the changes and returning the results <a href="#035012be047e431d8904686ec9915b8f">#</a>
Expand All @@ -148,7 +148,7 @@ <h3 id="178ff7d455e44a619b67d911a6aecba7">
Accumulating the bulk-update result <a href="#178ff7d455e44a619b67d911a6aecba7">#</a>
</h3>
<p>
So far, I've assumed that the final <code>BulkUpdateResult</code> class is just a simple immutable container without much functionality. If, however, we add some copy-and-update functions to it, we can use that to aggregate the result, instead of an anonymous tuple.
So far, I've assumed that the final <code>BulkUpdateResult</code> class is just a simple immutable container without much functionality. If, however, we add some copy-and-update functions to it, we can use them to aggregate the result, instead of an anonymous tuple.
</p>
<p>
<pre><span style="color:blue;">internal</span>&nbsp;<span style="color:#2b91af;">BulkUpdateResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Store</span>(<span style="color:#2b91af;">ShoppingListItem</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">item</span>)&nbsp;=&gt;
Expand Down Expand Up @@ -191,7 +191,7 @@ <h3 id="32e680ea1dbb4bc7bc097e8fcfcb90e9">
Parallel Sequence <a href="#32e680ea1dbb4bc7bc097e8fcfcb90e9">#</a>
</h3>
<p>
If the tasks you want to traverse are thread-safe, you might consider making it concurrent. You can use <a href="https://learn.microsoft.com/dotnet/api/system.threading.tasks.task.whenall">Task.WhenAll</a> for that. It has the same type as <code>Sequence</code>, so if you can live with the extra non-determinism that comes with parallel execution, you can use that instead:
If the tasks you want to traverse are thread-safe, you might consider making the traversal concurrent. You can use <a href="https://learn.microsoft.com/dotnet/api/system.threading.tasks.task.whenall">Task.WhenAll</a> for that. It has the same type as <code>Sequence</code>, so if you can live with the extra non-determinism that comes with parallel execution, you can use that instead:
</p>
<p>
<pre><span style="color:blue;">internal</span>&nbsp;<span style="color:blue;">static</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&lt;<span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;&nbsp;<span style="color:#74531f;">Sequence</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:blue;">this</span>&nbsp;<span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">Task</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">tasks</span>)
Expand Down

0 comments on commit d680d85

Please sign in to comment.