scide: LookupDialog - redo lookup on classes after partial lookup
[supercollider.git] / HelpSource / Guides / J-concepts-in-SC.schelp
bloba864a8bcc9ffd86ad9a4733c8403c829dda55e16
1 title:: J concepts in SC
2 summary:: An overview of concepts borrowed from J
3 categories:: Language
5 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
6 complex notions of iteration implicitly.
8 The following are some concepts borrowed from or inspired by J.
9 Thinking about multidimensional arrays can be both mind bending and mind expanding.
10 It may take some effort to grasp what is happening in these examples.
12 section:: Filling arrays
13 iota fills an array with a counter
14 code::
15 z = Array.iota(2, 3, 3);
16 z.rank; // 3 dimensions
17 z.shape; // gives the sizes of the dimensions
18 z = z.reshape(3, 2, 3); // reshape changes the dimensions of an array
19 z.rank; // 3 dimensions
20 z.shape;
23 fill a multidimensional array
24 code::
25 // 2 dimensions
26 Array.fill([3,3], { 1.0.rand.round(0.01) });
27 Array.fill([2,3], {|i,j| i@j });
29 // 3 dimensions
30 Array.fill([2, 2, 2], { 1.0.rand.round(0.01) });
31 Array.fill([2, 3, 4], {|i,j,k| [i, j, k].join });
33 // a shorter variant of the above:
34 {|i,j,k| [i, j, k].join } ! [2, 3, 4];
36 // more dimensions
37 Array.fill([2, 2, 4, 2], {|...args| args.join });
41 section:: Creating arrays
42 using dup to create arrays
43 code::
44 (1..4) dup: 3;
45 100.rand dup: 10;
46 {100.rand} dup: 10;
47 {100.rand} dup: 3 dup: 4;
48 {{100.rand} dup: 3} dup: 4;
49 {|i| i.squared} dup: 10;
50 {|i| i.nthPrime} dup: 10;
51 { |i, j, k| i * j } dup: [5, 5]; // multidimensional dup
53 ! is an abbreviation of dup
54 code::
55 (1..4) ! 3;
56 100.rand ! 10;
57 {100.rand} ! 10;
58 {100.rand} ! 3 ! 4;
59 {{100.rand} ! 3} ! 4;
60 {|i| i.squared} ! 10;
61 {|i| i.nthPrime} ! 10;
62 { |i, j| i * j } ! [5, 5];
65 other ways to do the same thing:
66 code::
67 // partial application
68 _.squared ! 10;
69 _.nthPrime ! 10;
71 // operating on a list
72 (0..9).squared;
73 (0..9).nthPrime;
76 section:: Operator adverbs
77 Adverbs are a third argument passed to binary operators that modifies how they iterate over
78 SequenceableCollections or Streams. See the link::Reference/Adverbs:: help file for more information.
79 code::
80 [10, 20, 30, 40, 50] + [1, 2, 3]; // normal
81 [10, 20, 30, 40, 50] +.f [1, 2, 3]; // folded
82 [10, 20, 30, 40, 50] +.s [1, 2, 3]; // shorter
83 [10, 20, 30, 40, 50] +.x [1, 2, 3]; // cross
84 [10, 20, 30, 40, 50] +.t [1, 2, 3]; // table
87 section:: Operator depth
88 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.
89 A binary operator can be given a depth at which to operate. Negative depths iterate the opposite operand.
90 These are better understood by example. It is not currently possible to combine adverb and depth.
91 code::
92 z = Array.iota(3,3);
93 y = [100, 200, 300];
94 z + y;
95 z +.0 y; // same as the above. y added to each row of z
96 z +.1 y; // y added to each column of z
97 z +.2 y; // y added to each element of z
98 z +.-1 y; // z added to each element of y
101 subsection:: deepCollect
102 deepCollect operates a function at different dimensions or depths in an array.
103 code::
104 z = Array.iota(3, 2, 3);
105 f = {|item| item.reverse };
106 z.deepCollect(0, f);
107 z.deepCollect(1, f);
108 z.deepCollect(2, f);
110 f = {|item| item.stutter };
111 z.deepCollect(0, f);
112 z.deepCollect(1, f);
113 z.deepCollect(2, f);
116 section:: Sections of multidimensional arrays
117 slice can get sections of multidimensional arrays.
118 nil gets all the indices of a dimension.
119 code::
120 z = Array.iota(4, 5);
121 z.slice(nil, (1..3));
122 z.slice(2, (1..3));
123 z.slice((2..3), (0..2));
124 z.slice((1..3), 3);
125 z.slice(2, 3);
127 z = Array.iota(3, 3, 3);
128 z.slice([0,1], [1,2], [0,2]);
129 z.slice(nil, nil, [0,2]);
130 z.slice(1);
131 z.slice(nil, 1);
132 z.slice(nil, nil, 1);
133 z.slice(nil, 2, 1);
134 z.slice(nil, 1, (1..2));
135 z.slice(1, [0,1]);
136 z.flop;
139 section:: Sorting order
140 generate a random array:
141 code::
142 z = {100.rand}.dup(10);
144 order returns an array of indices representing what would be the sorted order of the array:
145 code::
146 o = z.order;
147 y = z[o]; // using the order as an index returns the sorted array
149 calling order on the order returns an array of indices that returns the sorted array to the
150 original scrambled order:
151 code::
152 p = o.order;
153 x = y[p];
156 section:: Bubbling
157 bubbling wraps an item in an array of one element. it takes the depth and levels as arguments.
158 code::
159 z = Array.iota(4,4);
160 z.bubble;
161 z.bubble(1);
162 z.bubble(2);
163 z.bubble(0,2);
164 z.bubble(1,2);
165 z.bubble(2,2);
167 similarly, unbubble unwraps an Array if it contains a single element.
168 code::
169 5.unbubble;
170 [5].unbubble;
171 [[5]].unbubble;
172 [[5]].unbubble(0,2);
173 [4,5].unbubble;
174 [[4],[5]].unbubble;
175 [[4],[5]].unbubble(1);
176 z.bubble.unbubble;
177 z.bubble(1).unbubble(1);
178 z.bubble(2).unbubble(2);
181 section:: Laminating with the +++ operator
182 the +++ operator takes each item from the second list and appends it to the corresponding item
183 in the first list. If the second list is shorter, it wraps.
184 code::
185 z = Array.iota(5,2);
186 z +++ [77,88,99];
187 z +++ [[77,88,99]];
188 z +++ [[[77,88,99]]];
189 z +++ [ [[77]],[[88]],[[99]] ];
190 // same as:
191 z +++ [77,88,99].bubble;
192 z +++ [77,88,99].bubble(0,2);
193 z +++ [77,88,99].bubble(1,2);
195 z +++ [11,22,33].pyramidg;
196 z +++ [11,22,33].pyramidg.bubble;
197 z +++ [[11,22,33].pyramidg];
198 z +++ [[[11,22,33].pyramidg]];
202 z = (1..4);
203 10.do {|i|
204     z.pyramid(i+1).postln;
205     z.pyramidg(i+1).postln;
206     "".postln;
211 section:: reshapeLike
212 reshapeLike allows you to make one nested array be restructured in the same manner as another.
213 code::
214 a = [[10,20],[30, 40, 50], 60, 70, [80, 90]];
215 b = [[1, 2, [3, 4], [[5], 6], 7], 8, [[9]]];
216 a.reshapeLike(b);
217 b.reshapeLike(a);
219 If the lengths are different, the default behaviour is to wrap:
220 code::
221 a = [[10,20],[30, 40, 50]];
222 b = [[1, 2, [3, 4], [[5], 6], 7], 8, [[9]]];
223 a.reshapeLike(b);
225 but you can specify other index operators:
226 code::
227 a.reshapeLike(b, \foldAt);
229 a.reshapeLike(b, \clipAt);
231 a.reshapeLike(b, \at);
234 section:: measuring dimensionality and size
235 maxSizeAtDepth allows you to check the maximum array size at a given depth dimension
236 code::
237 [[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(2);
238 [[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(1);
239 [[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(0);
240 (0..3).collect([[1, 2, 3], [[41, 52], 5, 6], 1, 2, 3].maxSizeAtDepth(_)) // max sizes for each dimension
243 section:: inverting dimensions
244 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.
245 code::
246 [[1, 2, 3], [[41, 52], 5, 6]].flopDeep(2);
247 [[1, 2, 3], [[41, 52], 5, 6]].flopDeep(1);
248 [[1, 2, 3], [[41, 52], 5, 6]].flopDeep(0);
249 [[1, 2, 3], [[41, 52], 5, 6]].flopDeep; // without argument, flop from the deepest level
251 [[[10, 100, 1000], 2, 3], [[41, 52], 5, 6]].flopDeep(2); // shorter array wraps
252 [].flopDeep(1); // result is always one dimension higher.
253 [[]].flopDeep(4);
257 section:: allTuples
258 allTuples will generate all combinations of the sub arrays
259 code::
260 [[1, 2, 3], [4, 5], 6].allTuples;
261 [[1, 2, 3], [4, 5, 6, 7], [8, 9]].allTuples;