This file is indexed.

/usr/share/SuperCollider/HelpSource/Guides/J-concepts-in-SC.schelp is in supercollider-common 1:3.6.3~repack-5.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
title:: J concepts in SC
summary:: An overview of concepts borrowed from J
categories:: Language

The J programming language is a successor of APL (http://www.jsoftware.com). These languages are made for processing arrays of data and are able to express
complex notions of iteration implicitly.

The following are some concepts borrowed from or inspired by J.
Thinking about multidimensional arrays can be both mind bending and mind expanding.
It may take some effort to grasp what is happening in these examples.

section:: Filling arrays
iota fills an array with a counter
code::
z = Array.iota(2, 3, 3);
z.rank; // 3 dimensions
z.shape; // gives the sizes of the dimensions
z = z.reshape(3, 2, 3); // reshape changes the dimensions of an array
z.rank; // 3 dimensions
z.shape;
::

fill a multidimensional array
code::
// 2 dimensions
Array.fill([3,3], { 1.0.rand.round(0.01) });
Array.fill([2,3], {|i,j| i@j });

// 3 dimensions
Array.fill([2, 2, 2], { 1.0.rand.round(0.01) });
Array.fill([2, 3, 4], {|i,j,k| [i, j, k].join });

// a shorter variant of the above:
{|i,j,k| [i, j, k].join } ! [2, 3, 4];

// more dimensions
Array.fill([2, 2, 4, 2], {|...args| args.join });
::


section:: Creating arrays
using dup to create arrays
code::
(1..4) dup: 3;
100.rand dup: 10;
{100.rand} dup: 10;
{100.rand} dup: 3 dup: 4;
{{100.rand} dup: 3} dup: 4;
{|i| i.squared} dup: 10;
{|i| i.nthPrime} dup: 10;
{ |i, j, k| i * j } dup: [5, 5]; // multidimensional dup
::
! is an abbreviation of dup
code::
(1..4) ! 3;
100.rand ! 10;
{100.rand} ! 10;
{100.rand} ! 3 ! 4;
{{100.rand} ! 3} ! 4;
{|i| i.squared} ! 10;
{|i| i.nthPrime} ! 10;
{ |i, j| i * j } ! [5, 5];
::

other ways to do the same thing:
code::
// partial application
_.squared ! 10;
_.nthPrime ! 10;

// operating on a list
(0..9).squared;
(0..9).nthPrime;
::

section:: Operator adverbs
Adverbs are a third argument passed to binary operators that modifies how they iterate over
SequenceableCollections or Streams. See the link::Reference/Adverbs:: help file for more information.
code::
[10, 20, 30, 40, 50] + [1, 2, 3]; // normal
[10, 20, 30, 40, 50] +.f [1, 2, 3]; // folded
[10, 20, 30, 40, 50] +.s [1, 2, 3]; // shorter
[10, 20, 30, 40, 50] +.x [1, 2, 3]; // cross
[10, 20, 30, 40, 50] +.t [1, 2, 3]; // table
::

section:: Operator depth
J has a concept called verb rank, which is probably too complex to understand and implement in SC, but operator depth is similar and simpler.
A binary operator can be given a depth at which to operate. Negative depths iterate the opposite operand.
These are better understood by example. It is not currently possible to combine adverb and depth.
code::
z = Array.iota(3,3);
y = [100, 200, 300];
z + y;
z +.0 y; // same as the above. y added to each row of z
z +.1 y; // y added to each column of z
z +.2 y; // y added to each element of z
z +.-1 y; // z added to each element of y
::

subsection:: deepCollect
deepCollect operates a function at different dimensions or depths in an array.
code::
z = Array.iota(3, 2, 3);
f = {|item| item.reverse };
z.deepCollect(0, f);
z.deepCollect(1, f);
z.deepCollect(2, f);

f = {|item| item.stutter };
z.deepCollect(0, f);
z.deepCollect(1, f);
z.deepCollect(2, f);
::

section:: Sections of multidimensional arrays
slice can get sections of multidimensional arrays.
nil gets all the indices of a dimension.
code::
z = Array.iota(4, 5);
z.slice(nil, (1..3));
z.slice(2, (1..3));
z.slice((2..3), (0..2));
z.slice((1..3), 3);
z.slice(2, 3);

z = Array.iota(3, 3, 3);
z.slice([0,1], [1,2], [0,2]);
z.slice(nil, nil, [0,2]);
z.slice(1);
z.slice(nil, 1);
z.slice(nil, nil, 1);
z.slice(nil, 2, 1);
z.slice(nil, 1, (1..2));
z.slice(1, [0,1]);
z.flop;
::

section:: Sorting order
generate a random array:
code::
z = {100.rand}.dup(10);
::
order returns an array of indices representing what would be the sorted order of the array:
code::
o = z.order;
y = z[o]; // using the order as an index returns the sorted array
::
calling order on the order returns an array of indices that returns the sorted array to the
original scrambled order:
code::
p = o.order;
x = y[p];
::

section:: Bubbling
bubbling wraps an item in an array of one element. it takes the depth and levels as arguments.
code::
z = Array.iota(4,4);
z.bubble;
z.bubble(1);
z.bubble(2);
z.bubble(0,2);
z.bubble(1,2);
z.bubble(2,2);
::
similarly, unbubble unwraps an Array if it contains a single element.
code::
5.unbubble;
[5].unbubble;
[[5]].unbubble;
[[5]].unbubble(0,2);
[4,5].unbubble;
[[4],[5]].unbubble;
[[4],[5]].unbubble(1);
z.bubble.unbubble;
z.bubble(1).unbubble(1);
z.bubble(2).unbubble(2);
::

section:: Laminating with the +++ operator
the +++ operator takes each item from the second list and appends it to the corresponding item
in the first list. If the second list is shorter, it wraps.
code::
z = Array.iota(5,2);
z +++ [77,88,99];
z +++ [[77,88,99]];
z +++ [[[77,88,99]]];
z +++ [ [[77]],[[88]],[[99]] ];
// same as:
z +++ [77,88,99].bubble;
z +++ [77,88,99].bubble(0,2);
z +++ [77,88,99].bubble(1,2);

z +++ [11,22,33].pyramidg;
z +++ [11,22,33].pyramidg.bubble;
z +++ [[11,22,33].pyramidg];
z +++ [[[11,22,33].pyramidg]];


(
z = (1..4);
10.do {|i|
    z.pyramid(i+1).postln;
    z.pyramidg(i+1).postln;
    "".postln;
};
)
::

section:: reshapeLike
reshapeLike allows you to make one nested array be restructured in the same manner as another.
code::
a = [[10,20],[30, 40, 50], 60, 70, [80, 90]];
b = [[1, 2, [3, 4], [[5], 6], 7], 8, [[9]]];
a.reshapeLike(b);
b.reshapeLike(a);
::
If the lengths are different, the default behaviour is to wrap:
code::
a = [[10,20],[30, 40, 50]];
b = [[1, 2, [3, 4], [[5], 6], 7], 8, [[9]]];
a.reshapeLike(b);
::
but you can specify other index operators:
code::
a.reshapeLike(b, \foldAt);

a.reshapeLike(b, \clipAt);

a.reshapeLike(b, \at);
::

section:: measuring dimensionality and size
maxSizeAtDepth allows you to check the maximum array size at a given depth dimension
code::
[[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(2);
[[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(1);
[[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(0);
(0..3).collect([[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(_)) // max sizes for each dimension
::

section:: inverting dimensions
flopDeep allows you to to invert the outermost dimension with a dimension at any depth. This is analogous to flop, which does the same for 2-dimensional arrays.
code::
[[1, 2, 3], [[41, 52], 5, 6]].flopDeep(2);
[[1, 2, 3], [[41, 52], 5, 6]].flopDeep(1);
[[1, 2, 3], [[41, 52], 5, 6]].flopDeep(0);
[[1, 2, 3], [[41, 52], 5, 6]].flopDeep; // without argument, flop from the deepest level

[[[10, 100, 1000], 2, 3], [[41, 52], 5, 6]].flopDeep(2); // shorter array wraps
[].flopDeep(1); // result is always one dimension higher.
[[]].flopDeep(4);
::


section:: allTuples
allTuples will generate all combinations of the sub arrays
code::
[[1, 2, 3], [4, 5], 6].allTuples;
[[1, 2, 3], [4, 5, 6, 7], [8, 9]].allTuples;
::