aboutsummaryrefslogtreecommitdiff
path: root/docs/doc/couple.html
blob: e583b7f650fc0767238f26fa058d5fa379442ec8 (plain)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<head>
  <link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
  <link href="../style.css" rel="stylesheet"/>
  <title>BQN: Couple and Merge</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="couple-and-merge"><a class="header" href="#couple-and-merge">Couple and Merge</a></h1>
<p>Solo/Couple (<code><span class='Function'></span></code>) and Merge (<code><span class='Function'>&gt;</span></code>) are functions that build a higher-rank array out of <a href="array.html#cells">cells</a>. Each takes some input arrays with the same shape, and combines them into a single array that includes all their elements. For example, let's couple two arrays of shape <code><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span></code>:</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4p+ocOKGkDPigL81w5fijJzihpUzLCBx4oaQMuKAvzPipYoiYWJjZGVmIuKfqSAgIyBTaG93biBzaWRlIGJ5IHNpZGUKCnAg4omNIHEgICAjIHAgY291cGxlZCB0byBxCgriiaIgcCDiiY0gcQ==">↗️</a><pre>    <span class='Bracket'></span><span class='Value'>p</span><span class='Gets'></span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>5</span><span class='Function'>×</span><span class='Modifier'></span><span class='Function'></span><span class='Number'>3</span><span class='Separator'>,</span> <span class='Value'>q</span><span class='Gets'></span><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span><span class='Function'></span><span class='String'>&quot;abcdef&quot;</span><span class='Bracket'></span>  <span class='Comment'># Shown side by side
</span>┌─                    
· ┌─         ┌─       
  ╵ 0 3  6   ╵"abc    
    0 5 10     def"   
           ┘       ┘  
                     ┘

    <span class='Value'>p</span> <span class='Function'></span> <span class='Value'>q</span>   <span class='Comment'># p coupled to q
</span>┌─             
╎ 0   3   6    
  0   5   10   
               
  'a' 'b' 'c'  
  'd' 'e' 'f'  
              ┘

    <span class='Function'></span> <span class='Value'>p</span> <span class='Function'></span> <span class='Value'>q</span>
⟨ 2 2 3 ⟩
</pre>
<p>The result is an array with <code><span class='Value'>p</span></code> and <code><span class='Value'>q</span></code> for its major cells. It has two inner axes that are shared by <code><span class='Value'>p</span></code> and <code><span class='Value'>q</span></code>, preceded by an outer axis, with length 2 because there are two arguments. With no left argument, <code><span class='Function'></span></code> does something simpler: it just adds an axis of length 1 to the front. The argument goes solo, becoming the only major cell of the result.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omNIHEKCuKJoiDiiY0gcQ==">↗️</a><pre>    <span class='Function'></span> <span class='Value'>q</span>
┌─     
╎"abc  
  def" 
      ┘

    <span class='Function'></span> <span class='Function'></span> <span class='Value'>q</span>
⟨ 1 2 3 ⟩
</pre>
<p>Merge (<code><span class='Function'>&gt;</span></code>) takes one argument, but a nested one. <code><span class='Value'>𝕩</span></code> is an array of arrays, each with the same shape. The shape of the result is then the outer shape <code><span class='Function'></span><span class='Value'>𝕩</span></code> followed by this shared inner shape.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIGEg4oaQICJBQiLigL8iQ0QiIOKIvuKMnCAicnN0IuKAvyJ1dnci4oC/Inh5eiIKCj4gYQoK4omiIGEK4omiID4gYQ==">↗️</a><pre>    <span class='Function'></span> <span class='Value'>a</span> <span class='Gets'></span> <span class='String'>&quot;AB&quot;</span><span class='Ligature'></span><span class='String'>&quot;CD&quot;</span> <span class='Function'></span><span class='Modifier'></span> <span class='String'>&quot;rst&quot;</span><span class='Ligature'></span><span class='String'>&quot;uvw&quot;</span><span class='Ligature'></span><span class='String'>&quot;xyz&quot;</span>
┌─                         
╵ "ABrst" "ABuvw" "ABxyz"  
  "CDrst" "CDuvw" "CDxyz"  
                          ┘

    <span class='Function'>&gt;</span> <span class='Value'>a</span>
┌─       
╎"ABrst  
  ABuvw  
  ABxyz  
         
 ·CDrst  
  CDuvw  
  CDxyz" 
        ┘

    <span class='Function'></span> <span class='Value'>a</span>
⟨ 2 3 ⟩
    <span class='Function'></span> <span class='Function'>&gt;</span> <span class='Value'>a</span>
⟨ 2 3 5 ⟩
</pre>
<p>If <code><span class='Value'>𝕩</span></code> is empty, but has a <a href="fill.html">fill</a> element, then its shape is used for the inner shape. If it doesn't have a fill, the inner shape is assumed to be empty, so that the result is <code><span class='Value'>𝕩</span></code> with no changes.</p>
<p>Merge serves as a generalization of Solo and Couple, since Solo is <code><span class='Brace'>{</span><span class='Function'>&gt;</span><span class='Bracket'></span><span class='Value'>𝕩</span><span class='Bracket'></span><span class='Brace'>}</span></code> and Couple is <code><span class='Brace'>{</span><span class='Function'>&gt;</span><span class='Bracket'></span><span class='Value'>𝕨</span><span class='Separator'>,</span><span class='Value'>𝕩</span><span class='Bracket'></span><span class='Brace'>}</span></code>. These can be combined with <a href="pair.html">Pair</a>, giving <code><span class='Function'>&gt;</span></code> for both. Since the result of <code><span class='Function'></span></code> has rank 1, it can only add one dimension, but <code><span class='Function'>&gt;</span></code> can take any number of dimensions as its input.</p>
<h2 id="coupling-units"><a class="header" href="#coupling-units">Coupling units</a></h2>
<p>A note on the topic of Solo and Couple applied to <a href="enclose.html#whats-a-unit">units</a>. As always, one axis will be added, so that the result is a list (strangely, J's <a href="https://code.jsoftware.com/wiki/Vocabulary/commaco#dyadic">laminate</a> differs from Couple in this one case, as it adds an axis to get a shape <code><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>1</span></code> result). Solo on a unit is interchangeable with <a href="reshape.html">Deshape</a> (<code><span class='Function'></span></code>), and either primitive might be chosen for stylistic reasons. Couple on units is equivalent to <a href="join.html">Join-to</a> (<code><span class='Function'></span></code>), but this is an irregular form of Join-to because it is the only case where Join-to adds an axis to both arguments instead of just one. Couple should be preferred in this case.</p>
<p>As a consequence, <a href="pair.html">Pair</a> (<code><span class='Function'></span></code>) can be written <code><span class='Function'></span><span class='Modifier2'></span><span class='Function'>&lt;</span></code>, while <code><span class='Function'></span></code> is <code><span class='Function'>&gt;</span><span class='Modifier2'></span><span class='Function'></span></code> as discussed above. This gives the neat (but not useful) identities <code><span class='Function'></span> <span class='Gets'>←→</span> <span class='Function'>&gt;</span><span class='Modifier2'></span><span class='Function'></span><span class='Modifier2'></span><span class='Function'>&lt;</span></code>, and <code><span class='Function'></span> <span class='Gets'>←→</span> <span class='Function'>&gt;</span><span class='Modifier2'></span><span class='Function'></span><span class='Modifier2'></span><span class='Function'>&lt;</span></code>, which have the same form because adding <code><span class='Modifier2'></span><span class='Function'>&lt;</span></code> commutes with adding <code><span class='Function'>&gt;</span><span class='Modifier2'></span></code>.</p>
<h2 id="merge-and-array-theory"><a class="header" href="#merge-and-array-theory">Merge and array theory</a></h2>
<p>In all cases, what these functions do is more like reinterpreting existing data than creating new information. In fact, if we ignore the shape and look at the deshaped arrays involved in a call to Merge, we find that it just <a href="join.html">joins</a> them together. Essentially, Merge is a request to ensure that the inner arrays make up a homogeneous (not &quot;ragged&quot;) array, and then to consider them to be such an array. It's the same thing <a href="rank.html">Rank</a> does to combine the result cells from its operand into a single array.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIGEg4oaQICJBQiLigL8iQ0QiIOKIvuKMnCAicnN0IuKAvyJ1dnci4oC/Inh5eiIK4qWKID4gYQoK4qWKIOKlisKoIGEK4oi+IOKliiDipYrCqCBh">↗️</a><pre>    <span class='Function'></span> <span class='Function'>&gt;</span> <span class='Value'>a</span>
"ABrstABuvwABxyzCDrstCDuvwCDxyz"

    <span class='Function'></span> <span class='Function'></span><span class='Modifier'>¨</span> <span class='Value'>a</span>
⟨ "ABrst" "ABuvw" "ABxyz" "CDrst" "CDuvw" "CDxyz" ⟩
    <span class='Function'></span> <span class='Function'></span> <span class='Function'></span><span class='Modifier'>¨</span> <span class='Value'>a</span>
"ABrstABuvwABxyzCDrstCDuvwCDxyz"
</pre>
<p>Somewhat like <a href="map.html#table">Table</a> <code><span class='Modifier'></span></code>, Merge might be considered a fundamental way to build up multidimensional arrays from lists. In both cases rank-0 or <a href="enclose.html#whats-a-unit">unit</a> arrays are somewhat special. They are the <a href="fold.html#identity-values">identity value</a> of a function with Table, and <a href="enclose.html">Enclose</a> (<code><span class='Function'>&lt;</span></code>), which creates a unit, is a right inverse to Merge. Enclose is needed because Merge can't produce a rank 0 array on its own. Merge has another catch as well: it can't produce arrays with a 0 in the shape, except at the end, without relying on a fill element.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIGUg4oaQIOKfqOKfqcKoIOKGlTMK4omiID4gZQriiaIgPiA+IGU=">↗️</a><pre>    <span class='Function'></span> <span class='Value'>e</span> <span class='Gets'></span> <span class='Bracket'>⟨⟩</span><span class='Modifier'>¨</span> <span class='Function'></span><span class='Number'>3</span>
⟨ ⟨⟩ ⟨⟩ ⟨⟩ ⟩
    <span class='Function'></span> <span class='Function'>&gt;</span> <span class='Value'>e</span>
⟨ 3 0 ⟩
    <span class='Function'></span> <span class='Function'>&gt;</span> <span class='Function'>&gt;</span> <span class='Value'>e</span>
⟨ 3 0 ⟩
</pre>
<p>Above we start with a list of three empty arrays. After merging once we get a shape <code><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>0</span></code> array, sure, but what happens next? The shape added by another merge is the shared shape of that array's elements—and there aren't any! If the nested list kept some type information around then we might know, but extra type information is essentially how lists pretend to be arrays. True dynamic lists simply can't represent multidimensional arrays with a 0 in the middle of the shape. In this sense, arrays are a richer model than nested lists.</p>
<h2 id="definitions"><a class="header" href="#definitions">Definitions</a></h2>
<p>We can define <code><span class='Function'></span></code> as <code><span class='Function'>&gt;</span></code>. To complete the picture we should describe Merge fully. Merge is defined on an array argument <code><span class='Value'>𝕩</span></code> such that there's some shape <code><span class='Value'>s</span></code> satisfying <code><span class='Function'></span><span class='Modifier'>´</span><span class='Function'></span><span class='Paren'>(</span><span class='Value'>s</span><span class='Function'>≡≢</span><span class='Paren'>)</span><span class='Modifier'>¨</span><span class='Value'>𝕩</span></code>. If <code><span class='Value'>𝕩</span></code> is empty then any shape satisfies this expression; <code><span class='Value'>s</span></code> is then the shape of the <a href="fill.html">fill</a> if there is one, or otherwise <code><span class='Bracket'>⟨⟩</span></code>.</p>
<p>Then the result of Merge is <code><span class='Value'>𝕩</span><span class='Function'></span><span class='Modifier'>˜⌜</span><span class='Function'></span><span class='Value'>s</span></code>. Here, <a href="map.html#table">Table</a> is a nice way of combining outer and inner axes to produce the result; since the outer axes come first they should go on the left and the inner axes on the right. <code><span class='Value'>𝕩</span></code> is a natural choice of left argument, and because no concrete array can be used, the right argument is <code><span class='Function'></span><span class='Value'>s</span></code>, the array of indices into any element of <code><span class='Value'>𝕩</span></code>. Then <a href="pick.html">Pick</a> selects all the elements. If <code><span class='Value'>s</span></code> is empty, then <code><span class='Value'>𝕩</span></code> is allowed to contain atoms as well as unit arrays. Pick will implicitly treat them as arrays.</p>