<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="215312" data-post-id="215312">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimitarvp" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/120/38664_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimitarvp
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="giddie" data-post="11" data-topic="39983">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/48/34394_2.png" class="avatar"> giddie:</div>
<blockquote>
<p>What I’m suggesting is that semantically, <code>:ok | :error | :none</code> is exactly the same.</p>
</blockquote>
</aside>
<p>Ah, agreed.</p>
<aside class="quote no-group" data-username="giddie" data-post="11" data-topic="39983">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/48/34394_2.png" class="avatar"> giddie:</div>
<blockquote>
<p>Returning <code>nil</code> would mean that we’re not returning a <code>Result.maybe()</code>.</p>
</blockquote>
</aside>
<p>Agreed as well, <code>nil</code> should be avoided like the plague.</p>
<aside class="quote no-group" data-username="giddie" data-post="11" data-topic="39983">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/48/34394_2.png" class="avatar"> giddie:</div>
<blockquote>
<p>if I see an error such as <code>:none.hello/0 is undefined</code>, then I know what I’m dealing with is a <code>Result.maybe()</code></p>
</blockquote>
</aside>
<p>That works with many other return values though, including with a plain <code>:ok</code> or <code>:error</code> (no tuple return value, just a single atom).</p>
<hr>
<p>As another Rust guy I can see where you’re coming from. But my view is that beyond avoiding <code>nil</code> at all costs, the rest is kind of achievable with fairly vanilla Elixir. But I get the need: you want chainable / pipeable value, which is fair.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215312" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-215312" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215312"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="215313" data-post-id="215313">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="hauleth" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/120/18942_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  hauleth
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="dimitarvp" data-post="12" data-topic="39983">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/48/38664_2.png" class="avatar"> dimitarvp:</div>
<blockquote>
<p>including with a plain <code>:ok</code> or <code>:error</code> (no tuple return value, just a single atom)</p>
</blockquote>
</aside>
<p>Well, in old Erlang versions it worked with tuples as well (and <a href="https://github.com/erlang/otp/pull/1499" rel="noopener nofollow ugc">it still can be enabled via <code>tuple_calls</code> compile option</a>).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215313" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-215313" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215313"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="215314" data-post-id="215314">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="giddie" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/120/34394_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  giddie
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="dimitarvp" data-post="12" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/48/38664_2.png" class="avatar"> dimitarvp:</div>
<blockquote>
<aside class="quote no-group" data-username="giddie" data-post="11" data-topic="39983">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/48/34394_2.png" class="avatar"> giddie:</div>
<blockquote>
<p>if I see an error such as <code>:none.hello/0 is undefined</code>, then I know what I’m dealing with is a <code>Result.maybe()</code></p>
</blockquote>
</aside>
<p>That works with many other return values though, including with a plain <code>:ok</code> or <code>:error</code> (no tuple return value, just a single atom).</p>
</blockquote>
</aside>
<p>Yes, absolutely. The <code>ok_then</code> library will also accept any bare atom (<code>:some</code>, <code>:success</code>, <code>:ok</code>, …). It interprets these internally as <code>{:ok, {}}, {:some, {}}, ...</code>, so mapping functions will receive <code>{}</code> as the wrapped value, and that’s what <code>unwrap!()</code> would return too. It’s just that <code>:none</code> is returned by <code>Result.from/1</code> and <code>Result.map/2</code> if they receive <code>nil</code> as a value to wrap, and there are shorthand functions to handle <code>:none</code>, such as <code>default/2</code> and <code>none_then/2</code>.</p>
<p>So if you want, you could fall back to a bare <code>:ok</code> quite easily like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Result.from(nil)      # :none
|&gt; Result.default({}) # :ok

# or

Result.from(nil)         # :none
|&gt; Result.none_then(:ok) # :ok
</code></pre>
<aside class="quote no-group" data-username="dimitarvp" data-post="12" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/48/38664_2.png" class="avatar"> dimitarvp:</div>
<blockquote>
<p>As another Rust guy I can see where you’re coming from. But my view is that beyond avoiding <code>nil</code> at all costs, the rest is kind of achievable with fairly vanilla Elixir. But I get the need: you want chainable / pipeable value, which is fair.</p>
</blockquote>
</aside>
<p>I’d be interested in some testcases, actually. Could I tempt you to come up with some examples of vanilla Elixir that we could compare to an equivalent using the <code>ok_then</code> library?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215314" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-215314" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215314"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="215316" data-post-id="215316">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ondrej-tucek" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ondrej-tucek/120/11566_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ondrej-tucek
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>whereas ok_then accepts any tagged tuple (though <code>:ok</code>, <code>:error</code>, and <code>:none</code> have more convenient functions)</p>
</blockquote>
<p>According to my experiences it’s bad practice to return just <code>:ok</code> or <code>:error</code> (<code>nil</code> is questionable) from called functions (where the Result type has a sense). You did ecto query to db but nothing was found? The returned value isn’t an error, just return tuple <code>{:ok, "User not found"}</code>. Did you get an error? Return tuple <code>{:error, message}</code>. That’s Result type (success or fail, whereas maybe is value or not defined). These messages can be then shown on client. What tell you the returned information <code>:ok</code> or <code>:error</code>? So if you follow the KISS rule, just enough to define Result as  <code>Result.t() :: {:ok, any()} | {:error, msg}</code>.</p>
<blockquote>
<p>I also felt like the API wasn’t quite as full or consistent as I’d have liked.</p>
</blockquote>
<p>Okay what prevents to you write <code>{:ok, {:some, ...}}</code>?</p>
<blockquote>
<p>This helps because if I see an error such as <code>:none.hello/0</code> is undefined, then I know what I’m dealing with is a Result.maybe().</p>
</blockquote>
<p>I’m not sure if this is helpful. Yes, you’ll only know that you’ll deal with <code>Result.maybe()</code>. But you won’t know why. So you have to go back to your logs/stack trace/… and find what caused the error. Maybe it will be a nil in passing argument of called function and then you are back with dealing <code>nil</code>…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215316" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-215316" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215316"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="215322" data-post-id="215322">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="giddie" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/120/34394_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  giddie
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="ondrej-tucek" data-post="15" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ondrej-tucek/48/11566_2.png" class="avatar"> ondrej-tucek:</div>
<blockquote>
<blockquote>
<p>whereas ok_then accepts any tagged tuple (though <code>:ok</code>, <code>:error</code>, and <code>:none</code> have more convenient functions)</p>
</blockquote>
<p>According to my experiences it’s bad practice to return just <code>:ok</code> or <code>:error</code> (<code>nil</code> is questionable) from called functions (where the Result type has a sense).</p>
</blockquote>
</aside>
<p>I tend to agree, especially for errors. (I do think <code>:ok</code> makes sense in side-effect-only functions, e.g. logging, assertions.) My design philosophy for the library was to <em>accept</em> as much as possible as input, though. Functions will not crash even if the input is not a tagged tuple. Untagged input is interpreted internally as <code>{:untagged, value}</code>, though this only becomes visible if the function needs to act on the wrapped value:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">"hello"
|&gt; Result.unwrap!()
**(ArgumentError) Value is not tagged ok: {:untagged, "hello"}.

# also:

{:ok, 1, 2, 3}
|&gt; Result.unwrap!()
{1, 2, 3}
</code></pre>
<p>Also, I think Result pipelines can make sense within functions too; not just to process function return values. Especially when calling functions with unclear return value semantics:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">get_a_map_that_could_be_nil()        # could be nil
|&gt; Result.from()
|&gt; Result.map(&amp;Map.get(&amp;1, :my_key)) # skipped if map was nil; Map.get/2 could return nil
|&gt; Result.unwrap_or("default value") # will handle nil at _any_ point
</code></pre>
<p>This saves a couple of more verbose <code>case</code> expressions.</p>
<aside class="quote no-group quote-modified" data-username="ondrej-tucek" data-post="15" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ondrej-tucek/48/11566_2.png" class="avatar"> ondrej-tucek:</div>
<blockquote>
<p>You did ecto query to db but nothing was found? The returned value isn’t an error, just return tuple <code>{:ok, "User not found"}</code>. Did you get an error? Return tuple <code>{:error, message}</code>. That’s Result type.</p>
</blockquote>
</aside>
<p>Sure, that could make sense if you’re close to the UI:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">do_query()
|&gt; Result.error_then(fn
  :not_found -&gt;  {:ok, "User not found"}
  reason -&gt; {:error, reason}
end)

# or

do_query()
|&gt; Result.or_else(fn
  :error, :not_found -&gt; {:ok, "User not found"}
  :error, reason -&gt; {:error, reason}
end)

# and if you're only interested in logging the error:

do_query()
|&gt; Result.error_consume(&amp;Logger.error/1)  # :none
|&gt; Result.default("User not found")       # {:ok, "User not found"}
</code></pre>
<aside class="quote no-group" data-username="ondrej-tucek" data-post="15" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ondrej-tucek/48/11566_2.png" class="avatar"> ondrej-tucek:</div>
<blockquote>
<p>Okay what prevents to you write <code>{:ok, {:some, ...}}</code>?</p>
</blockquote>
</aside>
<p>I certainly considered this - it’s documented in the README. But ultimately I think the issue is that it can become quite difficult to read in log and console output, and the additional layer of unwrapping could break existing functions that expect <code>{:ok, value}</code>. So I combined the two types <code>{:ok, value} | {:error, reason}</code> and <code>{:some, value} | :none</code> into a single type: <code>{:ok, value} | :none | {:error, reason}</code>.</p>
<aside class="quote no-group quote-modified" data-username="ondrej-tucek" data-post="15" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ondrej-tucek/48/11566_2.png" class="avatar"> ondrej-tucek:</div>
<blockquote>
<blockquote>
<p>This helps because if I see an error such as <code>:none.hello/0</code> is undefined, then I know what I’m dealing with is a Result.maybe().</p>
</blockquote>
<p>I’m not sure if this is helpful. Yes, you’ll only know that you’ll deal with <code>Result.maybe()</code>. But you won’t know why. So you have to go back to your logs/stack trace/… and find what caused the error. Maybe it will be a nil in passing argument of called function and then you are back with dealing <code>nil</code>…</p>
</blockquote>
</aside>
<p>It’s possible, but I think it’s less likely: I’ve found that in practice, having a Result pipeline makes it more likely that I’ll consider default/fallback values at each point. When I call <code>Result.from/1</code>, I’m already thinking “this could be <code>:none</code>”, and when I call <code>Result.unwrap_or/2</code>, I’m forced to provide a default value. If I use <code>Result.unwrap!/1</code>, I’m reminded that it could raise.</p>
<p>So really, if I forget to unwrap a Result, I’m equally likely to get:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">** (BadMapError) expected a map, got: {:ok, %{}}
# or
** (BadMapError) expected a map, got: :none
</code></pre>
<p>Either way, personally I find it pretty easy to see that I just forgot to unwrap the Result. And unwrapping it will force me to specify a default value, or raise.</p>
<p>On the other hand, if I get: <code>** (BadMapError) expected a map, got: nil</code>, I get a sinking feeling, because it’s not clear I just forgot to unwrap a Result: it could equally well mean that the code runs fine 99% of the time when the value is usually a map, and this one time it was unexpectedly <code>nil</code> due to a race condition <img src="https://forum.elixirforum.com/images/emoji/apple/roll_eyes.png?v=15" title=":roll_eyes:" class="emoji" alt=":roll_eyes:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215322" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-215322" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215322"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="215334" data-post-id="215334">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="stevensonmt" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/120/20503_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  stevensonmt
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>This addresses a real desire for me having gotten used to Option/Result types with Rust and Elm. The discussion in this thread has shown how much thought you put into the API design. Thanks for putting this out!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215334" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-215334" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215334"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="215344" data-post-id="215344">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ondrej-tucek" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ondrej-tucek/120/11566_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ondrej-tucek
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you for your exhausting and clarifying post.</p>
<blockquote>
<p>I do think :ok makes sense in side-effect-only functions, e.g. logging, assertions.</p>
</blockquote>
<p>I agree</p>
<blockquote>
<p>My design philosophy for the library was to accept as much as possible as input, though. Functions will not crash even if the input is not a tagged tuple.</p>
</blockquote>
<p>I understood it from your previous posts. But in my/our case (with <a href="https://hexdocs.pm/result/api-reference.html" rel="noopener nofollow ugc">iodevs/Result</a>) mostly we put <code>:some</code> (with value) to the <code>map</code> (or list) and then call <code>Result.map()</code>, <code>Result.and_then()</code>, etc…  according to need.</p>
<p>So using iodevs/Result library you can write, e.g.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">user_id
|&gt; User.get_user()           # do_query fun, return Result.t(String.t(), User.t())
|&gt; Result.map(&amp;User.do_something(&amp;1,  user_anything)  # Result.t()
|&gt; ExMaybe.from_result()     # data or nil in case of error
|&gt; ExMaybe.with_default(User.default_settings())      # will handle nil at _any_ point
</code></pre>
<p>Or check our <a href="https://github.com/iodevs/qr_code/blob/master/lib/qr_code/placement.ex" rel="noopener nofollow ugc">QR_code</a> library for how we used iodevs/Result. The main core of iodevs/Result (and of course iodevs/ExMaybe) was strongly inspired by Elm Result type.</p>
<blockquote>
<p>if I forget to unwrap a Result, I’m equally likely to get:</p>
</blockquote>
<p>I get your point, but in error messages in your terminal/logs/… you also have the name of modules and functions which were called and of course the number of line in your ex file where error happened.</p>
<p>Something like</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">lib/module_name.ex:60:  ModuleName.do_update...
** (BadMapError) expected a map, got: nil
</code></pre>
<p>So you exactly know where you have to look at.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215344" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-215344" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215344"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="215348" data-post-id="215348">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimitarvp" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/120/38664_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimitarvp
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="giddie" data-post="16" data-topic="39983">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/48/34394_2.png" class="avatar"> giddie:</div>
<blockquote>
<p>I think the issue is that it can become quite difficult to read in log and console output</p>
</blockquote>
</aside>
<p>Sure, but our brain gets used to tune out the noise very quickly. I get your point but I am 50/50 about if it’s an issue that could get annoying with time.</p>
<aside class="quote no-group" data-username="giddie" data-post="16" data-topic="39983">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/48/34394_2.png" class="avatar"> giddie:</div>
<blockquote>
<p>and the additional layer of unwrapping could break existing functions that expect <code>{:ok, value}</code></p>
</blockquote>
</aside>
<p>Not sure I follow, can you give an example? I’d think that if you adopt a model or having more metadata in your result values then you’d make sure that all your project’s code is using them and then convert them at the edges of the outside world (internet) and your dependencies. Fairly standard deal when you decide to buy into a library’s value proposition.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215348" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-215348" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215348"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="215428" data-post-id="215428">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="giddie" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/120/34394_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  giddie
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="stevensonmt" data-post="17" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/48/20503_2.png" class="avatar"> stevensonmt:</div>
<blockquote>
<p>This addresses a real desire for me having gotten used to Option/Result types with Rust and Elm. The discussion in this thread has shown how much thought you put into the API design. Thanks for putting this out!</p>
</blockquote>
</aside>
<p>Thanks; I really appreciate you taking the time to say that <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215428" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-215428" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215428"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="215431" data-post-id="215431">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="giddie" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/giddie/120/34394_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  giddie
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="ondrej-tucek" data-post="18" data-topic="39983" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ondrej-tucek/48/11566_2.png" class="avatar"> ondrej-tucek:</div>
<blockquote>
<p>So using iodevs/Result library you can write, e.g.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">user_id
|&gt; User.get_user()           # do_query fun, return Result.t(String.t(), User.t())
|&gt; Result.map(&amp;User.do_something(&amp;1,  user_anything)  # Result.t()
|&gt; ExMaybe.from_result()     # data or nil in case of error
|&gt; ExMaybe.with_default(User.default_settings())      # will handle nil at _any_ point
</code></pre>
</blockquote>
</aside>
<p>Cool; seems like a reasonable workflow. I figured people must be handling these situations somehow with existing tools. But for my taste, I think the <code>ok_then</code> flow is a little cleaner:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">user_id
|&gt; User.get_user()   # Result.maybe(User.t(), any()) = {:ok, User.t()} | :none | {:error, any()}
|&gt; Result.map(&amp;User.modify_user(&amp;1, user_anything))  # Result.maybe(User.t(), any())
|&gt; Result.error_consume(&amp;Logger.error/1)  # If :error, log and replace with :none
|&gt; Result.unwrap_or(&amp;User.default/1)   # Can provide value or function for lazy evaluation
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215431" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/ok-then-the-swiss-army-knife-for-tagged-tuple-pipelines/39983/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-215431" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215431"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/39983/load_more?page=3">Load more posts (6 remaining)</a>
</div></template></turbo-stream>