1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
<head>
<link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
<link href="../style.css" rel="stylesheet"/>
<title>BQN: Assert and Catch</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">doc</a></div>
<h1 id="assert-and-catch"><a class="header" href="#assert-and-catch">Assert and Catch</a></h1>
<p>BQN provides some simple facilities for dealing with errors. Errors are an unusual sort of control flow; if possible, prefer to work with functions that return normally.</p>
<h2 id="assert"><a class="header" href="#assert">Assert</a></h2>
<p>BQN takes the position that errors exist to indicate exceptional conditions that the developer of a given program didn't expect. However, the types of errors that BQN naturally checks for, such as mismatched shapes in Couple (<code><span class='Function'>≍</span></code>), aren't always enough to detect exceptional conditions. Issues like numeric values that don't make physical sense will slip right through. BQN makes it easy for a programmer to check for these sorts of problems by building in the primitive Assert, written <code><span class='Function'>!</span></code>. This function checks whether <code><span class='Value'>𝕩</span></code> matches <code><span class='Number'>1</span></code>: if it does, then it does nothing and returns <code><span class='Value'>𝕩</span></code>, and otherwise it gives an error.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAyPTIgICMgUGFzc2VkCgohIDI9MyAgIyBGYWlsZWQ=">↗️</a><pre> <span class='Function'>!</span> <span class='Number'>2</span><span class='Function'>=</span><span class='Number'>2</span> <span class='Comment'># Passed
</span>1
<span class='Function'>!</span> <span class='Number'>2</span><span class='Function'>=</span><span class='Number'>3</span> <span class='Comment'># Failed
</span><span class='Error'>Error: Assertion error</span>
</pre>
<p>To pass, the right argument must be exactly the number <code><span class='Number'>1</span></code>; any other value causes an error. For example, an array of <code><span class='Number'>1</span></code>s still causes an error; use <code><span class='Function'>∧</span><span class='Modifier'>´</span><span class='Function'>⥊</span></code> to convert a boolean array to a single boolean that indicates whether all of its values are true.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAo4oinPeKIqOKMvsKsKeKMnMucIOKGlTIKCiEg4oinwrTipYogKOKIpz3iiKjijL7CrCnijJzLnCDihpUy">↗️</a><pre> <span class='Function'>!</span> <span class='Paren'>(</span><span class='Function'>∧=∨</span><span class='Modifier2'>⌾</span><span class='Function'>¬</span><span class='Paren'>)</span><span class='Modifier'>⌜˜</span> <span class='Function'>↕</span><span class='Number'>2</span>
<span class='Error'>Error: 2‿2⥊1‿1‿1‿1</span>
<span class='Function'>!</span> <span class='Function'>∧</span><span class='Modifier'>´</span><span class='Function'>⥊</span> <span class='Paren'>(</span><span class='Function'>∧=∨</span><span class='Modifier2'>⌾</span><span class='Function'>¬</span><span class='Paren'>)</span><span class='Modifier'>⌜˜</span> <span class='Function'>↕</span><span class='Number'>2</span>
1
</pre>
<p>Assert can take a left argument, which gives a message to be associated with the error. It's typical to use a string for <code><span class='Value'>𝕨</span></code> in order to display it to the programmer, but <code><span class='Value'>𝕨</span></code> can be any value.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Ik1lc3NhZ2UiICEgMAoK4p+o4oiYLCJhYmMiLMuc4p+pICEgJzAn">↗️</a><pre> <span class='String'>"Message"</span> <span class='Function'>!</span> <span class='Number'>0</span>
<span class='Error'>Error: Message</span>
<span class='Bracket'>⟨</span><span class='Modifier2'>∘</span><span class='Separator'>,</span><span class='String'>"abc"</span><span class='Separator'>,</span><span class='Modifier'>˜</span><span class='Bracket'>⟩</span> <span class='Function'>!</span> <span class='String'>'0'</span>
<span class='Error'>Error: ⟨∘,"abc",˜⟩</span>
</pre>
<p>In the 1-argument case, <code><span class='Value'>𝕩</span></code> is used for the error message if it's not <code><span class='Number'>1</span></code>. So an unconditional error can also be written this way:</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ISAiTWVzc2FnZSI=">↗️</a><pre> <span class='Function'>!</span> <span class='String'>"Message"</span>
<span class='Error'>Error: Message</span>
</pre>
<h3 id="computing-the-error-message-on-demand"><a class="header" href="#computing-the-error-message-on-demand">Computing the error message on demand</a></h3>
<p>Because the left argument to a function is always computed before the function is called, Assert <a href="../commentary/problems.html#assert-has-no-way-to-compute-the-error-message">doesn't let you</a> compute the error message only if there's an error. This might be a problem if the error message computation is slow or has side effects. There are a few ways to work around the issue:</p>
<ul>
<li>Handle bad inputs with ordinary if-then logic (perhaps using <a href="control.html">control structures</a>), not errors. This is probably the best path for user-facing applications where BQN's normal error display isn't wanted.</li>
<li>Write a function <code><span class='Function'>Message</span></code> to compute the message, and call <code><span class='Function'>!</span><span class='Modifier2'>∘</span><span class='Function'>Message</span><span class='Modifier2'>⍟</span><span class='Paren'>(</span><span class='Number'>1</span><span class='Modifier2'>⊸</span><span class='Function'>≢</span><span class='Paren'>)</span> <span class='Value'>𝕩</span></code> or similar instead of <code><span class='Function'>!</span></code>.</li>
<li>If the error will be caught elsewhere in the program, use a closure for the message and evaluate it when caught. With a function <code><span class='Function'>Message</span></code> as above, <code><span class='Value'>message</span> <span class='Function'>!</span> <span class='Value'>𝕩</span></code> works, and <code><span class='Brace'>{</span><span class='Value'>…</span><span class='Brace'>}</span><span class='Modifier'>˙</span><span class='Modifier2'>⊸</span><span class='Function'>!</span> <span class='Value'>𝕩</span></code> is a convenient syntax for block functions.</li>
</ul>
<h2 id="catch"><a class="header" href="#catch">Catch</a></h2>
<p>The <code><span class='Function'>Catch</span></code> modifier allows you to handle errors in BQN (at present, it's the only way to do so). It evaluates the function <code><span class='Function'>𝔽</span></code> normally. If this function completes without an error, Catch just returns that result. If not, it stops the error, and calls <code><span class='Function'>𝔾</span></code> with the original arguments instead.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oy94o6KJ3gnICJhYmNkIiAgIyBObyBlcnJvcgoK4oy94o6KJ3gnIDIgICAgICAgIyBDYW4ndCByZXZlcnNlIGEgdW5pdAoKMC41IOKMveKOiuKKoyDihpU2ICAgICMgQSB0d28tYXJndW1lbnQgZXhhbXBsZQ==">↗️</a><pre> <span class='Function'>⌽</span><span class='Modifier2'>⎊</span><span class='String'>'x'</span> <span class='String'>"abcd"</span> <span class='Comment'># No error
</span>"dcba"
<span class='Function'>⌽</span><span class='Modifier2'>⎊</span><span class='String'>'x'</span> <span class='Number'>2</span> <span class='Comment'># Can't reverse a unit
</span>'x'
<span class='Number'>0.5</span> <span class='Function'>⌽</span><span class='Modifier2'>⎊</span><span class='Function'>⊣</span> <span class='Function'>↕</span><span class='Number'>6</span> <span class='Comment'># A two-argument example
</span>0.5
</pre>
<p>Catch doesn't know anything about what an error <em>is</em>, just whether there was one or not. In fact, the idea of an error message doesn't feature at all in core BQN: it's purely part of the language environment. So you need a system value to access information about the error. Right now the only one is <code><span class='Function'>•CurrentError</span></code>, which is a function that returns a message for the error currently caught (if any).</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oy94o6K4oCiQ3VycmVudEVycm9yIDI=">↗️</a><pre> <span class='Function'>⌽</span><span class='Modifier2'>⎊</span><span class='Function'>•CurrentError</span> <span class='Number'>2</span>
"⌽: Argument cannot be a unit"
</pre>
|