diff options
Diffstat (limited to 'docs/doc/oop.html')
| -rw-r--r-- | docs/doc/oop.html | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/docs/doc/oop.html b/docs/doc/oop.html index a683a550..c2c597db 100644 --- a/docs/doc/oop.html +++ b/docs/doc/oop.html @@ -65,7 +65,7 @@ </tbody> </table> <h2 id="objects">Objects</h2> -<p>An object in BQN is simply a namespace: its fields and methods are variables in the namespace, and one of these can be accessed outside of the namespace with dot syntax if it's exported with <code><span class='Gets'>⇐</span></code>. Unexported variables are instance-private in OOP parlance, meaning that only they're only visible to the object containing them. They could be utilities, or hold state for the object. As an example, the object below implements the <a href="https://en.wikipedia.org/wiki/Tower_of_Hanoi">Tower of Hanoi</a> puzzle with five disks. You can view the state (a list of disks occupying each of the three rods) with <code><span class='Value'>towerOfHanoi.View</span></code>, or move the top disk from one rod to another with <code><span class='Value'>towerOfHanoi.Move</span></code>.</p> +<p>An object in BQN is simply a namespace: its fields and methods are variables in the namespace, and one of these can be accessed outside of the namespace with dot syntax if it's exported with <code><span class='Gets'>⇐</span></code>. Unexported variables are instance-private in OOP parlance, meaning that only they're only visible to the object containing them. They could be utilities, or hold state for the object. As an example, the object below implements the <a href="https://en.wikipedia.org/wiki/Tower_of_Hanoi">Tower of Hanoi</a> puzzle with five disks. You can view the state (a list of disks occupying each of the three rods) with <code><span class='Value'>towerOfHanoi.</span><span class='Function'>View</span></code>, or move the top disk from one rod to another with <code><span class='Value'>towerOfHanoi.</span><span class='Function'>Move</span></code>.</p> <pre><span class='Value'>towerOfHanoi</span> <span class='Gets'>←</span> <span class='Brace'>{</span> <span class='Value'>l</span> <span class='Gets'>←</span> <span class='Function'>↕</span><span class='Modifier'>¨</span><span class='Number'>5</span><span class='Ligature'>‿</span><span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>0</span> <span class='Function'>View</span> <span class='Gets'>⇐</span> <span class='Brace'>{</span><span class='Value'>𝕤</span> @@ -85,15 +85,15 @@ <p>Two fields <code><span class='Value'>l</span></code> and <code><span class='Function'>Transfer</span></code> aren't exported, for two different reasons. <code><span class='Value'>l</span></code> encodes the state of the tower, but it's often better to expose it with the function <code><span class='Function'>View</span></code> instead to allow the internal representation to be changed freely. <code><span class='Function'>Transfer</span></code> is just a utility function. While it's not dangerous to use outside of the object, there's no reason to expose it through <code><span class='Value'>towerOfHanoi</span></code>'s interface. If it's wanted in another place it should be moved to a common location.</p> <p>Here are the results of a few applications of these functions.</p> <pre> <span class='Value'>t</span> <span class='Gets'>←</span> <span class='Value'>towerOfHanoi</span> - <span class='Value'>t.View</span><span class='String'>@</span> + <span class='Value'>t.</span><span class='Function'>View</span><span class='String'>@</span> <span class='Bracket'>⟨</span> <span class='Bracket'>⟨</span> <span class='Number'>0</span> <span class='Number'>1</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟨⟩</span> <span class='Bracket'>⟨⟩</span> <span class='Bracket'>⟩</span> - <span class='Value'>t.Move</span> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>2</span> + <span class='Value'>t.</span><span class='Function'>Move</span> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>2</span> <span class='Bracket'>⟨</span> <span class='Bracket'>⟨</span> <span class='Number'>1</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟨⟩</span> <span class='Bracket'>⟨</span> <span class='Number'>0</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟩</span> - <span class='Value'>t.Move</span> <span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>2</span> + <span class='Value'>t.</span><span class='Function'>Move</span> <span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>2</span> <span class='Function'>!</span> <span class='String'>"No disk to move"</span> - <span class='Value'>t.Move</span> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>1</span> + <span class='Value'>t.</span><span class='Function'>Move</span> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>1</span> <span class='Bracket'>⟨</span> <span class='Bracket'>⟨</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟨</span> <span class='Number'>1</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟨</span> <span class='Number'>0</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟩</span> - <span class='Value'>t.Move</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>1</span> + <span class='Value'>t.</span><span class='Function'>Move</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>1</span> <span class='Bracket'>⟨</span> <span class='Bracket'>⟨</span> <span class='Number'>2</span> <span class='Number'>3</span> <span class='Number'>4</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟨</span> <span class='Number'>0</span> <span class='Number'>1</span> <span class='Bracket'>⟩</span> <span class='Bracket'>⟨⟩</span> <span class='Bracket'>⟩</span> </pre> <h2 id="classes">Classes</h2> @@ -119,18 +119,18 @@ <pre><span class='Function'>MakeQueue</span> <span class='Gets'>←</span> <span class='Brace'>{</span><span class='Value'>𝕤</span> <span class='Value'>t</span><span class='Gets'>←</span><span class='Value'>h</span><span class='Gets'>←</span><span class='Value'>e</span><span class='Gets'>←</span><span class='Brace'>{</span><span class='Function'>SetN</span><span class='Gets'>⇐</span><span class='Brace'>{</span><span class='Value'>h</span><span class='Gets'>↩</span><span class='Value'>𝕩</span><span class='Brace'>}}</span> <span class='Function'>Node</span><span class='Gets'>←</span><span class='Brace'>{</span><span class='Value'>v</span><span class='Gets'>⇐</span><span class='Value'>𝕩</span><span class='Separator'>⋄</span><span class='Value'>n</span><span class='Gets'>⇐</span><span class='Value'>e</span> <span class='Separator'>⋄</span> <span class='Function'>SetN</span><span class='Gets'>⇐</span><span class='Brace'>{</span><span class='Value'>n</span><span class='Gets'>↩</span><span class='Value'>𝕩</span><span class='Brace'>}}</span> - <span class='Function'>Push</span><span class='Gets'>⇐</span><span class='Brace'>{</span><span class='Value'>t.SetN</span> <span class='Value'>n</span><span class='Gets'>←</span><span class='Function'>Node</span> <span class='Value'>𝕩</span> <span class='Separator'>⋄</span> <span class='Value'>t</span><span class='Gets'>↩</span><span class='Value'>n</span><span class='Brace'>}</span> + <span class='Function'>Push</span><span class='Gets'>⇐</span><span class='Brace'>{</span><span class='Value'>t.</span><span class='Function'>SetN</span> <span class='Value'>n</span><span class='Gets'>←</span><span class='Function'>Node</span> <span class='Value'>𝕩</span> <span class='Separator'>⋄</span> <span class='Value'>t</span><span class='Gets'>↩</span><span class='Value'>n</span><span class='Brace'>}</span> <span class='Function'>Pop</span> <span class='Gets'>⇐</span><span class='Brace'>{</span><span class='Value'>𝕤</span><span class='Separator'>⋄</span><span class='Value'>v</span><span class='Gets'>←</span><span class='Value'>h.v</span><span class='Separator'>⋄</span><span class='Brace'>{</span><span class='Value'>t</span><span class='Gets'>↩</span><span class='Value'>𝕩</span><span class='Brace'>}</span><span class='Modifier2'>⍟</span><span class='Paren'>(</span><span class='Value'>e</span><span class='Modifier2'>⊸</span><span class='Function'>=</span><span class='Paren'>)</span><span class='Value'>h</span><span class='Gets'>↩</span><span class='Value'>h.n</span><span class='Separator'>⋄</span><span class='Value'>v</span><span class='Brace'>}</span> <span class='Brace'>}</span> </pre> -<p>Unlike a stack, a node's successor isn't known when it's created, and it has to be set. You might be inclined to make <code><span class='Value'>n</span></code> settable directly, but we'll get more mileage out of a setter function <code><span class='Function'>SetN</span></code>. This allows us to create a pseudo-node <code><span class='Value'>e</span></code> (for "empty") indicating there are no values in the queue. Because it has no <code><span class='Number'>.v</span></code> field, if <code><span class='Value'>h</span></code> is <code><span class='Value'>e</span></code> then <code><span class='Function'>Pop</span></code> gives an error (but in a real implementation you'd want to test explicitly instead in order to give an appropriate error message). In fact it doesn't have an <code><span class='Value'>n</span></code> field, and essentially uses the queue head <code><span class='Value'>h</span></code> instead. With this empty "node", the queue definition is straightforward. The only tricky part to remember is that if <code><span class='Function'>Pop</span></code> removes the last node, resulting in <code><span class='Value'>e</span><span class='Function'>=</span><span class='Value'>h</span></code>, then the tail has to be set to <code><span class='Value'>e</span></code> as well, or it will keep pointing to the removed node and cause bugs.</p> +<p>Unlike a stack, a node's successor isn't known when it's created, and it has to be set. You might be inclined to make <code><span class='Value'>n</span></code> settable directly, but we'll get more mileage out of a setter function <code><span class='Function'>SetN</span></code>. This allows us to create a pseudo-node <code><span class='Value'>e</span></code> (for "empty") indicating there are no values in the queue. Because it has no <code><span class='Value'>.v</span></code> field, if <code><span class='Value'>h</span></code> is <code><span class='Value'>e</span></code> then <code><span class='Function'>Pop</span></code> gives an error (but in a real implementation you'd want to test explicitly instead in order to give an appropriate error message). In fact it doesn't have an <code><span class='Value'>n</span></code> field, and essentially uses the queue head <code><span class='Value'>h</span></code> instead. With this empty "node", the queue definition is straightforward. The only tricky part to remember is that if <code><span class='Function'>Pop</span></code> removes the last node, resulting in <code><span class='Value'>e</span><span class='Function'>=</span><span class='Value'>h</span></code>, then the tail has to be set to <code><span class='Value'>e</span></code> as well, or it will keep pointing to the removed node and cause bugs.</p> <h2 id="composition">Composition</h2> <p>BQN classes don't support inheritance because there's no way to extend an existing class with new fields. But a lot of OOP enthusiasts these days are promoting <a href="https://en.wikipedia.org/wiki/Composition_over_inheritance">composition over inheritance</a>, and here BQN does pretty well. Forwarding methods from another class is as simple as a multiple assignment, like <code><span class='Bracket'>⟨</span><span class='Function'>View</span><span class='Bracket'>⟩</span></code> below (in a real program <code><span class='Value'>undoableTowerOfHanoi</span></code> should almost certainly be a class, but I introduced <code><span class='Value'>towerOfHanoi</span></code> before classes, and I'm not about to write it again just to add an <code><span class='Value'>𝕤</span></code>).</p> <pre><span class='Value'>undoableTowerOfHanoi</span> <span class='Gets'>←</span> <span class='Brace'>{</span> <span class='Function'>Push</span><span class='Ligature'>‿</span><span class='Function'>Pop</span> <span class='Gets'>←</span> <span class='Function'>MakeStack</span><span class='String'>@</span> <span class='Comment'># Copy methods as private </span> <span class='Bracket'>⟨</span><span class='Function'>View</span><span class='Bracket'>⟩</span> <span class='Gets'>⇐</span> <span class='Value'>t</span><span class='Gets'>←</span><span class='Value'>towerOfHanoi</span> <span class='Comment'># Copy and export -</span> <span class='Function'>Move</span> <span class='Gets'>⇐</span> <span class='Value'>t.Move</span> <span class='Function'>⊣</span> <span class='Function'>Push</span> - <span class='Function'>Undo</span> <span class='Gets'>⇐</span> <span class='Value'>t.Move</span><span class='Modifier2'>∘</span><span class='Function'>⌽</span><span class='Modifier2'>∘</span><span class='Function'>Pop</span> +</span> <span class='Function'>Move</span> <span class='Gets'>⇐</span> <span class='Value'>t.</span><span class='Function'>Move</span> <span class='Function'>⊣</span> <span class='Function'>Push</span> + <span class='Function'>Undo</span> <span class='Gets'>⇐</span> <span class='Value'>t.</span><span class='Function'>Move</span><span class='Modifier2'>∘</span><span class='Function'>⌽</span><span class='Modifier2'>∘</span><span class='Function'>Pop</span> <span class='Brace'>}</span> </pre> <p>This class composes a Tower of Hanoi with an undo stack that stores previous moves. To undo a move from <code><span class='Value'>a</span></code> to <code><span class='Value'>b</span></code>, it moves from <code><span class='Value'>b</span></code> to <code><span class='Value'>a</span></code>, although if you felt really fancy you might define <code><span class='Function'>Move</span><span class='Modifier'>⁼</span></code> in <code><span class='Value'>towerOfHanoi</span></code> instead with <code><span class='Function'>𝕊</span><span class='Modifier'>⁼</span><span class='Value'>𝕩:</span> <span class='Function'>𝕊⌽</span><span class='Value'>𝕩</span></code>.</p> |
