Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 243328ce99 | |||
| 30c9acc2bb | |||
| 16ecac7329 | |||
| f66c5e7f18 | |||
| 22bd9025fb | |||
| 8f27c5e552 | |||
| cd80913346 | |||
| cb5951794d | |||
| 2f1f5ed2f8 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
*.exe
|
*.exe
|
||||||
|
.vscode/
|
||||||
23
README.md
Normal file
23
README.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# op
|
||||||
|
Generic, exception-free return values.
|
||||||
|
|
||||||
|
OP stands for "Operation Result".
|
||||||
|
|
||||||
|
This module contains a generic type that can be used as a return type for operations that could fail. It adds additional messages to the result.
|
||||||
|
This improves upon the [options module](https://nim-lang.org/docs/options.html) in that additional messages can be passed along with the presence or absence of a value.
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
``` nim
|
||||||
|
import op
|
||||||
|
|
||||||
|
proc divide(a, b: int): OP[float] =
|
||||||
|
## This could fail
|
||||||
|
if b == 0:
|
||||||
|
return fail "Cannot divide by zero!"
|
||||||
|
else:
|
||||||
|
return ok a / b # Wrap the result
|
||||||
|
|
||||||
|
let r = divide(42, 0)
|
||||||
|
assert r.isOk == false
|
||||||
|
assert r.error == "Cannot divide by zero!"
|
||||||
|
```
|
||||||
180
doc/op.html
180
doc/op.html
@@ -97,29 +97,50 @@ function main() {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<ul class="simple simple-toc" id="toc-list">
|
<ul class="simple simple-toc" id="toc-list">
|
||||||
|
<li><a class="reference" id="basic-usage_toc" href="#basic-usage">Basic Usage</a></li>
|
||||||
<li>
|
<li>
|
||||||
<a class="reference reference-toplevel" href="#7" id="57">Types</a>
|
<a class="reference reference-toplevel" href="#7" id="57">Types</a>
|
||||||
<ul class="simple simple-toc-section">
|
<ul class="simple simple-toc-section">
|
||||||
<li><a class="reference" href="#OP"
|
<li><a class="reference" href="#Either"
|
||||||
title="OP[T] = object of RootObj
|
title="Either[A; B] = object
|
||||||
case isOk*: bool
|
case isA*: bool
|
||||||
of true:
|
of true:
|
||||||
val*: T
|
a*: A
|
||||||
|
|
||||||
of false:
|
of false:
|
||||||
error*: string"><wbr />OP<span class="attachedType"></span></a></li>
|
b*: B"><wbr />Either<span class="attachedType"></span></a></li>
|
||||||
|
<li><a class="reference" href="#OP"
|
||||||
|
title="OP[T] = Either[T, string]"><wbr />OP<span class="attachedType"></span></a></li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="reference reference-toplevel" href="#12" id="62">Procs</a>
|
<a class="reference reference-toplevel" href="#18" id="68">Templates</a>
|
||||||
<ul class="simple simple-toc-section">
|
<ul class="simple simple-toc-section">
|
||||||
<li><a class="reference" href="#ok%2CT"
|
<li><a class="reference" href="#checkA.t%2CEither"
|
||||||
|
title="checkA(self: Either): bool"><wbr />check<wbr />A<span class="attachedType">Either</span></a></li>
|
||||||
|
<li><a class="reference" href="#getA.t%2CEither%5BA%2CB%5D"
|
||||||
|
title="getA[A; B](self: Either[A, B]): A"><wbr />get<wbr />A<span class="attachedType">Either</span></a></li>
|
||||||
|
<li><a class="reference" href="#getB.t%2CEither%5BA%2CB%5D"
|
||||||
|
title="getB[A; B](self: Either[A, B]): B"><wbr />get<wbr />B<span class="attachedType">Either</span></a></li>
|
||||||
|
<li><a class="reference" href="#isOK.t%2COP"
|
||||||
|
title="isOK(self: OP): bool"><wbr />is<wbr />OK<span class="attachedType">OP</span></a></li>
|
||||||
|
<li><a class="reference" href="#val.t%2COP"
|
||||||
|
title="val(self: OP): auto"><wbr />val<span class="attachedType">OP</span></a></li>
|
||||||
|
<li><a class="reference" href="#error.t%2COP"
|
||||||
|
title="error(self: OP): auto"><wbr />error<span class="attachedType">OP</span></a></li>
|
||||||
|
<li><a class="reference" href="#ok.t%2CT"
|
||||||
title="ok[T](val: T): OP[T]"><wbr />ok<span class="attachedType">OP</span></a></li>
|
title="ok[T](val: T): OP[T]"><wbr />ok<span class="attachedType">OP</span></a></li>
|
||||||
<li><a class="reference" href="#fail%2COP%2Cstring"
|
<li><a class="reference" href="#ok.t%2COP%5BT%5D%2CT"
|
||||||
|
title="ok[T](self: var OP[T]; val: T)"><wbr />ok<span class="attachedType">OP</span></a></li>
|
||||||
|
<li><a class="reference" href="#fail.t%2C%2Cstring"
|
||||||
|
title="fail[T; ](O: type OP[T]; msg: string): O:type"><wbr />fail<span class="attachedType">OP</span></a></li>
|
||||||
|
<li><a class="reference" href="#fail.t%2Ctypedesc%2Cstring"
|
||||||
|
title="fail(T: typedesc; msg: string): OP[T]"><wbr />fail<span class="attachedType">OP</span></a></li>
|
||||||
|
<li><a class="reference" href="#fail.t%2COP%2Cstring"
|
||||||
title="fail(op: OP; msg: string): OP"><wbr />fail<span class="attachedType">OP</span></a></li>
|
title="fail(op: OP; msg: string): OP"><wbr />fail<span class="attachedType">OP</span></a></li>
|
||||||
<li><a class="reference" href="#fail%2Cstring"
|
<li><a class="reference" href="#fail.t%2Cstatic%5Bstring%5D"
|
||||||
title="fail[T](msg: string): OP[T]"><wbr />fail<span class="attachedType">OP</span></a></li>
|
title="fail(msg: static[string]): auto"><wbr />fail<span class="attachedType"></span></a></li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
@@ -130,25 +151,47 @@ function main() {
|
|||||||
<div class="nine columns" id="content">
|
<div class="nine columns" id="content">
|
||||||
<div id="tocRoot"></div>
|
<div id="tocRoot"></div>
|
||||||
|
|
||||||
<p class="module-desc"><p>This module contains a generic type that can be used as a return type for operations that could fail. It adds additional messages to the result.</p>
|
<p class="module-desc"><table class="docinfo" frame="void" rules="none"><col class="docinfo-name" /><col class="docinfo-content" /><tbody valign="top"><tr><th class="docinfo-name">Version:</th><td> 1.0.0</td></tr>
|
||||||
<p>OP stands for "Operation result".</p>
|
<tr><th class="docinfo-name">Author:</th><td> luxick <op@luxick.de></td></tr>
|
||||||
</p>
|
</tbody></table><p>OP stands for "Operation Result".</p>
|
||||||
|
<p>This module contains a generic type that can be used as a return type for operations that could fail. It adds additional messages to the result.</p>
|
||||||
|
<p>This module improves upon the <a class="reference external" href="https://nim-lang.org/docs/options.html">options module</a> in that additional messages can be passed along with the presence or absence of a value.</p>
|
||||||
|
|
||||||
|
<h1><a class="toc-backref" id="basic-usage" href="#basic-usage">Basic Usage</a></h1><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">divide</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">OP</span><span class="Punctuation">[</span><span class="Identifier">float</span><span class="Punctuation">]</span> <span class="Operator">=</span>
|
||||||
|
<span class="Comment">## This could fail</span>
|
||||||
|
<span class="Keyword">if</span> <span class="Identifier">b</span> <span class="Operator">==</span> <span class="DecNumber">0</span><span class="Punctuation">:</span>
|
||||||
|
<span class="Keyword">return</span> <span class="Identifier">fail</span> <span class="StringLit">"Cannot divide by zero!"</span>
|
||||||
|
<span class="Keyword">else</span><span class="Punctuation">:</span>
|
||||||
|
<span class="Keyword">return</span> <span class="Identifier">ok</span> <span class="Identifier">a</span> <span class="Operator">/</span> <span class="Identifier">b</span> <span class="Comment"># Wrap the result</span>
|
||||||
|
|
||||||
|
<span class="Keyword">let</span> <span class="Identifier">r</span> <span class="Operator">=</span> <span class="Identifier">divide</span><span class="Punctuation">(</span><span class="DecNumber">42</span><span class="Punctuation">,</span> <span class="DecNumber">0</span><span class="Punctuation">)</span>
|
||||||
|
<span class="Identifier">assert</span> <span class="Identifier">r</span><span class="Operator">.</span><span class="Identifier">isOk</span> <span class="Operator">==</span> <span class="Identifier">false</span>
|
||||||
|
<span class="Identifier">assert</span> <span class="Identifier">r</span><span class="Operator">.</span><span class="Identifier">error</span> <span class="Operator">==</span> <span class="StringLit">"Cannot divide by zero!"</span></pre></p>
|
||||||
<div class="section" id="7">
|
<div class="section" id="7">
|
||||||
<h1><a class="toc-backref" href="#7">Types</a></h1>
|
<h1><a class="toc-backref" href="#7">Types</a></h1>
|
||||||
<dl class="item">
|
<dl class="item">
|
||||||
<a id="OP"></a>
|
<a id="Either"></a>
|
||||||
<dt><pre><a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span> <span class="Other">=</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">RootObj</span>
|
<dt><pre><a href="op.html#Either"><span class="Identifier">Either</span></a><span class="Other">[</span><span class="Identifier">A</span><span class="Other">;</span> <span class="Identifier">B</span><span class="Other">]</span> <span class="Other">=</span> <span class="Keyword">object</span>
|
||||||
<span class="Keyword">case</span> <span class="Identifier">isOk</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">bool</span>
|
<span class="Keyword">case</span> <span class="Identifier">isA</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">bool</span>
|
||||||
<span class="Keyword">of</span> <span class="Identifier">true</span><span class="Other">:</span>
|
<span class="Keyword">of</span> <span class="Identifier">true</span><span class="Other">:</span>
|
||||||
<span class="Identifier">val</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">T</span>
|
<span class="Identifier">a</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">A</span>
|
||||||
|
|
||||||
<span class="Keyword">of</span> <span class="Identifier">false</span><span class="Other">:</span>
|
<span class="Keyword">of</span> <span class="Identifier">false</span><span class="Other">:</span>
|
||||||
<span class="Identifier">error</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">string</span>
|
<span class="Identifier">b</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">B</span>
|
||||||
|
|
||||||
</pre></dt>
|
</pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|
||||||
Object to wrap the result of an operation<ul class="simple"><li><tt class="docutils literal"><span class="pre">isOk</span></tt>: Indicates if the operation was successful</li>
|
An <tt class="docutils literal"><span class="pre">Either</span></tt> object can hold either one value or the other, but never both
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="OP"></a>
|
||||||
|
<dt><pre><a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span> <span class="Other">=</span> <a href="op.html#Either"><span class="Identifier">Either</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">,</span> <span class="Identifier">string</span><span class="Other">]</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p>Object to wrap the result of an operation. Alias of <tt class="docutils literal"><span class="pre">Either</span></tt> with a string as error message</p>
|
||||||
|
<p>The type is discriminated by the <tt class="docutils literal"><span class="pre">isOK</span></tt> bool. So it is an compiler error to try to access the value without checking if the operation was successful.</p>
|
||||||
|
<ul class="simple"><li><tt class="docutils literal"><span class="pre">isOk</span></tt>: Indicates if the operation was successful</li>
|
||||||
<li><tt class="docutils literal"><span class="pre">val</span></tt>: If successful, this will hold the real result value</li>
|
<li><tt class="docutils literal"><span class="pre">val</span></tt>: If successful, this will hold the real result value</li>
|
||||||
<li><tt class="docutils literal"><span class="pre">error</span></tt>: Otherwise this will hold an error message</li>
|
<li><tt class="docutils literal"><span class="pre">error</span></tt>: Otherwise this will hold an error message</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -157,18 +200,91 @@ Object to wrap the result of an operation<ul class="simple"><li><tt class="docut
|
|||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
</dl></div>
|
</dl></div>
|
||||||
<div class="section" id="12">
|
<div class="section" id="18">
|
||||||
<h1><a class="toc-backref" href="#12">Procs</a></h1>
|
<h1><a class="toc-backref" href="#18">Templates</a></h1>
|
||||||
<dl class="item">
|
<dl class="item">
|
||||||
<a id="ok,T"></a>
|
<a id="checkA.t,Either"></a>
|
||||||
<dt><pre><span class="Keyword">proc</span> <a href="#ok%2CT"><span class="Identifier">ok</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">val</span><span class="Other">:</span> <span class="Identifier">T</span><span class="Other">)</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span></pre></dt>
|
<dt><pre><span class="Keyword">template</span> <a href="#checkA.t%2CEither"><span class="Identifier">checkA</span></a><span class="Other">(</span><span class="Identifier">self</span><span class="Other">:</span> <a href="op.html#Either"><span class="Identifier">Either</span></a><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">bool</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="getA.t,Either[A,B]"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#getA.t%2CEither%5BA%2CB%5D"><span class="Identifier">getA</span></a><span class="Other">[</span><span class="Identifier">A</span><span class="Other">;</span> <span class="Identifier">B</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">self</span><span class="Other">:</span> <a href="op.html#Either"><span class="Identifier">Either</span></a><span class="Other">[</span><span class="Identifier">A</span><span class="Other">,</span> <span class="Identifier">B</span><span class="Other">]</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">A</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="getB.t,Either[A,B]"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#getB.t%2CEither%5BA%2CB%5D"><span class="Identifier">getB</span></a><span class="Other">[</span><span class="Identifier">A</span><span class="Other">;</span> <span class="Identifier">B</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">self</span><span class="Other">:</span> <a href="op.html#Either"><span class="Identifier">Either</span></a><span class="Other">[</span><span class="Identifier">A</span><span class="Other">,</span> <span class="Identifier">B</span><span class="Other">]</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">B</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="isOK.t,OP"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#isOK.t%2COP"><span class="Identifier">isOK</span></a><span class="Other">(</span><span class="Identifier">self</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">bool</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="val.t,OP"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#val.t%2COP"><span class="Identifier">val</span></a><span class="Other">(</span><span class="Identifier">self</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">auto</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="error.t,OP"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#error.t%2COP"><span class="Identifier">error</span></a><span class="Other">(</span><span class="Identifier">self</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">auto</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="ok.t,T"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#ok.t%2CT"><span class="Identifier">ok</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">val</span><span class="Other">:</span> <span class="Identifier">T</span><span class="Other">)</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|
||||||
Wraps the given value in a successful operation result.
|
Wraps the given value in a successful operation result.
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<a id="fail,OP,string"></a>
|
<a id="ok.t,OP[T],T"></a>
|
||||||
<dt><pre><span class="Keyword">proc</span> <a href="#fail%2COP%2Cstring"><span class="Identifier">fail</span></a><span class="Other">(</span><span class="Identifier">op</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">;</span> <span class="Identifier">msg</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">OP</span></pre></dt>
|
<dt><pre><span class="Keyword">template</span> <a href="#ok.t%2COP%5BT%5D%2CT"><span class="Identifier">ok</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">self</span><span class="Other">:</span> <span class="Keyword">var</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">;</span> <span class="Identifier">val</span><span class="Other">:</span> <span class="Identifier">T</span><span class="Other">)</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
Set the result to the given value
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="fail.t,,string"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#fail.t%2C%2Cstring"><span class="Identifier">fail</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">;</span> <span class="Other">]</span><span class="Other">(</span><span class="Identifier">O</span><span class="Other">:</span> <span class="Keyword">type</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">;</span> <span class="Identifier">msg</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">O:type</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p>Will create a new operation result with the given error message. The type for the operation result is given explicitly.</p>
|
||||||
|
<p><strong>See Also:</strong></p>
|
||||||
|
<ul class="simple"><li><a class="reference external" href="#fail,OP,string">fail proc</a></li>
|
||||||
|
<li><a class="reference external" href="#fail.t,static[string]">fail template</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="fail.t,typedesc,string"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#fail.t%2Ctypedesc%2Cstring"><span class="Identifier">fail</span></a><span class="Other">(</span><span class="Identifier">T</span><span class="Other">:</span> <span class="Identifier">typedesc</span><span class="Other">;</span> <span class="Identifier">msg</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p>Will create a new operation result with the given error message. The type for the operation result is given explicitly.</p>
|
||||||
|
<p><strong>See Also:</strong></p>
|
||||||
|
<ul class="simple"><li><a class="reference external" href="#fail,OP,string">fail proc</a></li>
|
||||||
|
<li><a class="reference external" href="#fail.t,static[string]">fail template</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<a id="fail.t,OP,string"></a>
|
||||||
|
<dt><pre><span class="Keyword">template</span> <a href="#fail.t%2COP%2Cstring"><span class="Identifier">fail</span></a><span class="Other">(</span><span class="Identifier">op</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">;</span> <span class="Identifier">msg</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">OP</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|
||||||
Will create a new operation result with the given error message. The type for the operation result is taken from the <tt class="docutils literal"><span class="pre">op</span></tt> argument.
|
Will create a new operation result with the given error message. The type for the operation result is taken from the <tt class="docutils literal"><span class="pre">op</span></tt> argument.
|
||||||
@@ -181,19 +297,11 @@ Will create a new operation result with the given error message. The type for th
|
|||||||
<span class="Identifier">assert</span> <span class="Identifier">data</span><span class="Other">.</span><span class="Identifier">error</span> <span class="Operator">==</span> <span class="StringLit">"Not implemented!"</span></pre>
|
<span class="Identifier">assert</span> <span class="Identifier">data</span><span class="Other">.</span><span class="Identifier">error</span> <span class="Operator">==</span> <span class="StringLit">"Not implemented!"</span></pre>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<a id="fail,string"></a>
|
<a id="fail.t,static[string]"></a>
|
||||||
<dt><pre><span class="Keyword">proc</span> <a href="#fail%2Cstring"><span class="Identifier">fail</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">msg</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span><span class="Other">:</span> <a href="op.html#OP"><span class="Identifier">OP</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span></pre></dt>
|
<dt><pre><span class="Keyword">template</span> <a href="#fail.t%2Cstatic%5Bstring%5D"><span class="Identifier">fail</span></a><span class="Other">(</span><span class="Identifier">msg</span><span class="Other">:</span> <span class="Identifier">static</span><span class="Other">[</span><span class="Identifier">string</span><span class="Other">]</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">auto</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|
||||||
<p>Will create a new operation result with the given error message. The type for the operation result is given explicitly.</p>
|
|
||||||
<p><strong>See Also:</strong></p>
|
|
||||||
<ul class="simple"><li><a class="reference external" href="#fail,OP,string">fail proc</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p><strong class="examples_text">Examples:</strong></p>
|
|
||||||
<pre class="listing"><span class="Keyword">let</span> <span class="Identifier">res</span> <span class="Other">=</span> <span class="Identifier">fail</span><span class="Other">[</span><span class="Identifier">seq</span><span class="Other">[</span><span class="Identifier">float</span><span class="Other">]</span><span class="Other">]</span> <span class="StringLit">"Something is wrong!"</span>
|
|
||||||
<span class="Identifier">assert</span> <span class="Identifier">res</span><span class="Other">.</span><span class="Identifier">isOk</span> <span class="Operator">==</span> <span class="Identifier">false</span>
|
|
||||||
<span class="Identifier">assert</span> <span class="Identifier">res</span><span class="Other">.</span><span class="Identifier">error</span> <span class="Operator">==</span> <span class="StringLit">"Something is wrong!"</span></pre>
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
@@ -206,7 +314,7 @@ Will create a new operation result with the given error message. The type for th
|
|||||||
<div class="twelve-columns footer">
|
<div class="twelve-columns footer">
|
||||||
<span class="nim-sprite"></span>
|
<span class="nim-sprite"></span>
|
||||||
<br/>
|
<br/>
|
||||||
<small style="color: var(--hint);">Made with Nim. Generated: 2020-07-01 21:23:47 UTC</small>
|
<small style="color: var(--hint);">Made with Nim. Generated: 2020-07-07 13:52:22 UTC</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "1.0.0"
|
version = "2.0.1"
|
||||||
author = "luxick"
|
author = "luxick"
|
||||||
description = "Generic result type for operations that can fail."
|
description = "Generic result type for operations that can fail."
|
||||||
license = "GPL-2.0"
|
license = "GPL-2.0"
|
||||||
@@ -10,5 +10,9 @@ srcDir = "src"
|
|||||||
|
|
||||||
requires "nim >= 1.2.4"
|
requires "nim >= 1.2.4"
|
||||||
|
|
||||||
task genDocs, "Generate Docs":
|
task docs, "Generate Docs":
|
||||||
exec "nim doc --project -o:doc src/op.nim"
|
exec "nim doc --project -o:doc src/op.nim"
|
||||||
|
|
||||||
|
task bench, "Runs the benchmark code":
|
||||||
|
exec "nim c -r benchmarks/bench.nim"
|
||||||
|
|
||||||
|
|||||||
98
src/op.nim
98
src/op.nim
@@ -1,26 +1,86 @@
|
|||||||
|
## :Version: 1.0.0
|
||||||
|
## :Author: luxick <op@luxick.de>
|
||||||
|
##
|
||||||
|
## OP stands for "Operation Result".
|
||||||
|
##
|
||||||
## This module contains a generic type that can be used as a return type
|
## This module contains a generic type that can be used as a return type
|
||||||
## for operations that could fail. It adds additional messages to the result.
|
## for operations that could fail. It adds additional messages to the result.
|
||||||
##
|
##
|
||||||
## OP stands for "Operation result".
|
##
|
||||||
|
## This module improves upon the `options module<https://nim-lang.org/docs/options.html>`_
|
||||||
|
## in that additional messages can be passed along with the presence or absence of a value.
|
||||||
|
##
|
||||||
|
## Basic Usage
|
||||||
|
## -----------
|
||||||
|
## .. code-block:: nim
|
||||||
|
##
|
||||||
|
## proc divide(a, b: int): OP[float] =
|
||||||
|
## ## This could fail
|
||||||
|
## if b == 0:
|
||||||
|
## return fail "Cannot divide by zero!"
|
||||||
|
## else:
|
||||||
|
## return ok a / b # Wrap the result
|
||||||
|
##
|
||||||
|
## let r = divide(42, 0)
|
||||||
|
## assert r.isOk == false
|
||||||
|
## assert r.error == "Cannot divide by zero!"
|
||||||
|
|
||||||
type
|
type
|
||||||
OP*[T] = object of RootObj
|
Either*[A, B] = object
|
||||||
## Object to wrap the result of an operation
|
## An `Either` object can hold either one value or the other, but never both
|
||||||
|
case isA*: bool
|
||||||
|
of true:
|
||||||
|
a*: A
|
||||||
|
of false:
|
||||||
|
b*: B
|
||||||
|
|
||||||
|
OP*[T] = Either[T, string]
|
||||||
|
## Object to wrap the result of an operation.
|
||||||
|
## Alias of `Either` with a string as error message
|
||||||
|
##
|
||||||
|
## The type is discriminated by the `isOK` bool.
|
||||||
|
## So it is an compiler error to try to access the value without checking
|
||||||
|
## if the operation was successful.
|
||||||
##
|
##
|
||||||
## - `isOk`: Indicates if the operation was successful
|
## - `isOk`: Indicates if the operation was successful
|
||||||
## - `val`: If successful, this will hold the real result value
|
## - `val`: If successful, this will hold the real result value
|
||||||
## - `error`: Otherwise this will hold an error message
|
## - `error`: Otherwise this will hold an error message
|
||||||
case isOk*: bool
|
|
||||||
of true:
|
|
||||||
val*: T
|
|
||||||
of false:
|
|
||||||
error*: string
|
|
||||||
|
|
||||||
proc ok*[T](val: T): OP[T] =
|
template checkA*(self: Either): bool = self.isA
|
||||||
|
template getA*[A, B](self: Either[A, B]): A = self.a
|
||||||
|
template getB*[A, B](self: Either[A, B]): B = self.b
|
||||||
|
|
||||||
|
template isOK*(self: OP): bool = checkA(self)
|
||||||
|
template val*(self: OP): auto = getA(self)
|
||||||
|
template error*(self: OP): auto = getB(self)
|
||||||
|
|
||||||
|
template ok*[T](val: T): OP[T] =
|
||||||
## Wraps the given value in a successful operation result.
|
## Wraps the given value in a successful operation result.
|
||||||
OP[T](isOK: true, val: val)
|
OP[T](isA: true, a: val)
|
||||||
|
|
||||||
proc fail*(op: OP, msg: string): OP =
|
template ok*[T](self: var OP[T], val: T) =
|
||||||
|
## Set the result to the given value
|
||||||
|
self = ok val
|
||||||
|
|
||||||
|
template fail*[T](O: type OP[T], msg: string): O =
|
||||||
|
## Will create a new operation result with the given error message.
|
||||||
|
## The type for the operation result is given explicitly.
|
||||||
|
##
|
||||||
|
## **See Also:**
|
||||||
|
## - `fail proc<#fail,OP,string>`_
|
||||||
|
## - `fail template<#fail.t,static[string]>`_
|
||||||
|
OP[T](isA: false, b: msg)
|
||||||
|
|
||||||
|
template fail*(T: typedesc, msg: string): OP[T] =
|
||||||
|
## Will create a new operation result with the given error message.
|
||||||
|
## The type for the operation result is given explicitly.
|
||||||
|
##
|
||||||
|
## **See Also:**
|
||||||
|
## - `fail proc<#fail,OP,string>`_
|
||||||
|
## - `fail template<#fail.t,static[string]>`_
|
||||||
|
OP[typeof(T)](isA: false, b: msg)
|
||||||
|
|
||||||
|
template fail*(op: OP, msg: string): OP =
|
||||||
## Will create a new operation result with the given error message.
|
## Will create a new operation result with the given error message.
|
||||||
## The type for the operation result is taken from the `op` argument.
|
## The type for the operation result is taken from the `op` argument.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
@@ -30,18 +90,6 @@ proc fail*(op: OP, msg: string): OP =
|
|||||||
let data = someProc()
|
let data = someProc()
|
||||||
assert data.isOk == false
|
assert data.isOk == false
|
||||||
assert data.error == "Not implemented!"
|
assert data.error == "Not implemented!"
|
||||||
OP(isOK: false, error: msg)
|
fail(typeof(op), msg)
|
||||||
|
|
||||||
proc fail*[T](msg: string): OP[T] =
|
|
||||||
## Will create a new operation result with the given error message.
|
|
||||||
## The type for the operation result is given explicitly.
|
|
||||||
##
|
|
||||||
## **See Also:**
|
|
||||||
## - `fail proc
|
|
||||||
## <#fail,OP,string>`_
|
|
||||||
runnableExamples:
|
|
||||||
let res = fail[seq[float]] "Something is wrong!"
|
|
||||||
assert res.isOk == false
|
|
||||||
assert res.error == "Something is wrong!"
|
|
||||||
OP[T](isOK: false, error: msg)
|
|
||||||
|
|
||||||
|
template fail*(msg: static[string]): auto = fail(typeof(result), msg)
|
||||||
128
tests/tests.nim
128
tests/tests.nim
@@ -3,36 +3,110 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import op
|
import op
|
||||||
|
|
||||||
test "Check OK":
|
suite "Basic tests":
|
||||||
let test = ok 1
|
proc divide(a, b: int): OP[float] =
|
||||||
check test.isOk == true
|
if b == 0:
|
||||||
|
return fail "Cannot divide by zero!"
|
||||||
|
else:
|
||||||
|
return ok a / b
|
||||||
|
|
||||||
test "Check fail":
|
test "Check OK":
|
||||||
let test = op.fail[int] "no data here"
|
let test = ok 1
|
||||||
check test.isOk == false
|
check test.isOk == true
|
||||||
|
|
||||||
test "Check proc results":
|
test "Check fail":
|
||||||
proc createValue: OP[string] =
|
let test = int.fail "no data here"
|
||||||
let myString = "This is test code!"
|
check test.isOk == false
|
||||||
ok myString
|
|
||||||
let data = createValue()
|
|
||||||
check data.isOk
|
|
||||||
check data.val == "This is test code!"
|
|
||||||
|
|
||||||
test "Check failing proc":
|
test "Check proc results":
|
||||||
proc someProc(): OP[int] =
|
proc createValue: OP[string] =
|
||||||
result.fail "Not implemented!"
|
let myString = "This is test code!"
|
||||||
|
ok myString
|
||||||
|
let r = createValue()
|
||||||
|
check r.isOk
|
||||||
|
check r.val == "This is test code!"
|
||||||
|
|
||||||
let data = someProc()
|
test "Check failing result proc":
|
||||||
assert data.isOk == false
|
proc someProc(): OP[int] =
|
||||||
assert data.error == "Not implemented!"
|
result.fail "Not implemented!"
|
||||||
|
|
||||||
test "Check changing result":
|
let data = someProc()
|
||||||
proc checker(): OP[int] =
|
assert data.isOk == false
|
||||||
result = ok 42
|
assert data.error == "Not implemented!"
|
||||||
# something happend here
|
|
||||||
result = result.fail "data got corrupted"
|
|
||||||
|
|
||||||
let data = checker()
|
test "Check failing typedesc proc ":
|
||||||
check data.isOk == false
|
proc someProc(): OP[int] =
|
||||||
check data.error == "data got corrupted"
|
op.fail(int, "Not implemented!")
|
||||||
|
|
||||||
|
let data = someProc()
|
||||||
|
assert data.isOk == false
|
||||||
|
assert data.error == "Not implemented!"
|
||||||
|
|
||||||
|
test "Check failing type param proc ":
|
||||||
|
proc someProc(): OP[int] =
|
||||||
|
fail(int, "Not implemented!")
|
||||||
|
|
||||||
|
let data = someProc()
|
||||||
|
assert data.isOk == false
|
||||||
|
assert data.error == "Not implemented!"
|
||||||
|
|
||||||
|
test "Check changing result":
|
||||||
|
proc checker(): OP[int] =
|
||||||
|
result = ok 42
|
||||||
|
# something happend here
|
||||||
|
result = result.fail "data got corrupted"
|
||||||
|
|
||||||
|
let data = checker()
|
||||||
|
check data.isOk == false
|
||||||
|
check data.error == "data got corrupted"
|
||||||
|
|
||||||
|
test "Check divider OK":
|
||||||
|
let r = divide(12, 6)
|
||||||
|
check r.isOk == true
|
||||||
|
check r.val == 2
|
||||||
|
|
||||||
|
test "Check implicit fail type":
|
||||||
|
let r = divide(1, 0)
|
||||||
|
check r.isOk == false
|
||||||
|
check r.error == "Cannot divide by zero!"
|
||||||
|
|
||||||
|
test "Check case":
|
||||||
|
let r = divide(1, 2)
|
||||||
|
case r.isOK:
|
||||||
|
of true:
|
||||||
|
check r.val == 0.5
|
||||||
|
of false:
|
||||||
|
echo r.error
|
||||||
|
|
||||||
|
test "Check hiding of Either":
|
||||||
|
let r = divide(1, 2)
|
||||||
|
case r.isOK:
|
||||||
|
of true:
|
||||||
|
check r.val == 0.5
|
||||||
|
of false:
|
||||||
|
echo r.error
|
||||||
|
|
||||||
|
test "Expect invalid field":
|
||||||
|
let r = divide(1, 2)
|
||||||
|
expect FieldError:
|
||||||
|
echo r.error
|
||||||
|
|
||||||
|
test "Expect in case":
|
||||||
|
let r = divide(1, 2)
|
||||||
|
case r.isOK:
|
||||||
|
of true:
|
||||||
|
expect FieldError:
|
||||||
|
echo r.error
|
||||||
|
of false:
|
||||||
|
echo r.error
|
||||||
|
|
||||||
|
# These will not work. How could this be done?
|
||||||
|
# test "Expect access before check":
|
||||||
|
# let r = divide(1, 2)
|
||||||
|
# expect FieldError:
|
||||||
|
# echo r.val
|
||||||
|
|
||||||
|
# test "Expect invalid field after check":
|
||||||
|
# let r = divide(1, 2)
|
||||||
|
# if r.isOK:
|
||||||
|
# echo r.error
|
||||||
Reference in New Issue
Block a user