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
|
<head>
<link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
<link href="../style.css" rel="stylesheet"/>
<title>BQN: Join</title>
</head>
<div class="nav"><a href="https://github.com/mlochbaum/BQN">BQN</a></div>
<h1 id="join">Join</h1>
<p>Join (<code><span class='Function'>∾</span></code>) is an extension of the monadic function <a href="https://aplwiki.com/wiki/Raze">Raze</a> from A+ and J to arbitrary argument ranks. It has the same relationship to Join to, the dyadic function sharing the same glyph, as <a href="couple.html">Merge</a> (<code><span class='Function'>></span></code>) does to Couple (<code><span class='Function'>≍</span></code>): <code><span class='Value'>a</span><span class='Function'>≍</span><span class='Value'>b</span></code> is <code><span class='Function'>></span><span class='Value'>a</span><span class='Ligature'>‿</span><span class='Value'>b</span></code> and <code><span class='Value'>a</span><span class='Function'>∾</span><span class='Value'>b</span></code> is <code><span class='Function'>∾</span><span class='Value'>a</span><span class='Ligature'>‿</span><span class='Value'>b</span></code>. While Merge and Couple combine arrays (the elements of Merge's argument, or the arguments themselves for Couple) along a new leading axis, Join and Join to combine them along the existing leading axis. Both Merge and Join can also be called on a higher-rank array, causing Merge to add multiple leading axes while Join combines elements along multiple existing axes.</p>
<p>Join can be used to combine several strings into a single string, like <code><span class='Value'>array.join</span><span class='Paren'>()</span></code> in Javascript (but it doesn't force the result to be a string).</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oi+InRpbWUi4oC/InRvIuKAvyJqb2luIuKAvyJzb21lIuKAvyJ3b3JkcyI=&run">↗️</a><pre> <span class='Function'>∾</span><span class='String'>"time"</span><span class='Ligature'>‿</span><span class='String'>"to"</span><span class='Ligature'>‿</span><span class='String'>"join"</span><span class='Ligature'>‿</span><span class='String'>"some"</span><span class='Ligature'>‿</span><span class='String'>"words"</span>
"timetojoinsomewords"
</pre>
<p>To join with a separator in between, we might prepend the separator to each string, then remove the leading separator after joining. Another approach would be to insert the separator array as an element between each pair of array elements before calling Join.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MeKGk+KIvicgJ+KIvsKoInRpbWUi4oC/InRvIuKAvyJqb2luIuKAvyJzb21lIuKAvyJ3b3JkcyI=&run">↗️</a><pre> <span class='Number'>1</span><span class='Function'>↓∾</span><span class='String'>' '</span><span class='Function'>∾</span><span class='Modifier'>¨</span><span class='String'>"time"</span><span class='Ligature'>‿</span><span class='String'>"to"</span><span class='Ligature'>‿</span><span class='String'>"join"</span><span class='Ligature'>‿</span><span class='String'>"some"</span><span class='Ligature'>‿</span><span class='String'>"words"</span>
"time to join some words"
</pre>
<p>Join requires each element of its argument to be an array, and their ranks to match exactly. No rank extension is performed.</p>
<pre> <span class='Function'>∾</span><span class='String'>"abc"</span><span class='Ligature'>‿</span><span class='String'>'d'</span><span class='Ligature'>‿</span><span class='String'>"ef"</span> <span class='Comment'># Includes an atom
</span><span class='Function'>RANK</span> <span class='Function'>ERROR</span>
<span class='Function'>∾</span><span class='String'>"abc"</span><span class='Ligature'>‿</span><span class='Paren'>(</span><span class='Function'><</span><span class='String'>'d'</span><span class='Paren'>)</span><span class='Ligature'>‿</span><span class='String'>"ef"</span> <span class='Comment'># Includes a scalar
</span><span class='Function'>RANK</span> <span class='Function'>ERROR</span>
</pre>
<p>However, Join has higher-dimensional uses as well. Given a rank-<code><span class='Value'>m</span></code> array of rank-<code><span class='Value'>n</span></code> arrays (requiring <code><span class='Value'>m</span><span class='Function'>≤</span><span class='Value'>n</span></code>), it will merge arrays along their first <code><span class='Value'>m</span></code> axes. For example, if the argument is a matrix of matrices representing a <a href="https://en.wikipedia.org/wiki/Block_matrix">block matrix</a>, Join will give the corresponding unblocked matrix as its result.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIG0g4oaQICgz4oC/MeKIvuKMnDTigL8y4oC/NSkg4qWKwqggMuKAvzPipYrihpU2CuKIviBtICAjIEpvaW4gYWxsIHRoYXQgdG9nZXRoZXI=&run">↗️</a><pre> <span class='Function'>⊢</span> <span class='Value'>m</span> <span class='Gets'>←</span> <span class='Paren'>(</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Function'>∾</span><span class='Modifier'>⌜</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>5</span><span class='Paren'>)</span> <span class='Function'>⥊</span><span class='Modifier'>¨</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Function'>⥊↕</span><span class='Number'>6</span>
┌─
╵ ┌─ ┌─ ┌─
╵ 0 0 0 0 ╵ 1 1 ╵ 2 2 2 2 2
0 0 0 0 1 1 2 2 2 2 2
0 0 0 0 1 1 2 2 2 2 2
┘ ┘ ┘
┌─ ┌─ ┌─
╵ 3 3 3 3 ╵ 4 4 ╵ 5 5 5 5 5
┘ ┘ ┘
┘
<span class='Function'>∾</span> <span class='Value'>m</span> <span class='Comment'># Join all that together
</span>┌─
╵ 0 0 0 0 1 1 2 2 2 2 2
0 0 0 0 1 1 2 2 2 2 2
0 0 0 0 1 1 2 2 2 2 2
3 3 3 3 4 4 5 5 5 5 5
┘
</pre>
<p>Join has fairly strict requirements on the shapes of its argument elements—although less strict than those of Merge, which requires they all have identical shape. Suppose the argument to Join has rank <code><span class='Value'>m</span></code>. Each of its elements must have the same rank, <code><span class='Value'>n</span></code>, which is at least <code><span class='Value'>m</span></code>. The trailing shapes <code><span class='Value'>m</span><span class='Function'>↓</span><span class='Modifier2'>⟜</span><span class='Function'>≢</span><span class='Modifier'>¨</span><span class='Value'>𝕩</span></code> must all be identical (the trailing shape <code><span class='Value'>m</span><span class='Function'>↓≢∾</span><span class='Value'>𝕩</span></code> of the result will match these shapes as well). The other entries in the leading shapes need not be the same, but the shape of an element along a particular axis must depend only on the location of the element along that axis in the full array. For a list argument this imposes no restriction, since the one leading shape element is allowed to depend on position along the only axis. But for higher ranks the structure quickly becomes more rigid.</p>
<p>To state this requirement more formally in BQN, we say that there is some list <code><span class='Value'>s</span></code> of lists of lengths, so that <code><span class='Paren'>(</span><span class='Function'>≢</span><span class='Modifier'>¨</span><span class='Value'>s</span><span class='Paren'>)</span><span class='Function'>≡≢</span><span class='Value'>𝕩</span></code>. We require element <code><span class='Value'>i</span><span class='Function'>⊑</span><span class='Value'>𝕩</span></code> to have shape <code><span class='Value'>i</span><span class='Function'>⊑</span><span class='Modifier'>¨</span><span class='Value'>s</span></code>. Then the first <code><span class='Value'>m</span></code> axes of the result are <code><span class='Function'>+</span><span class='Modifier'>´¨</span><span class='Value'>s</span></code>.</p>
|