Earlier quoted context omitted.
You've reproduced the most trivial example, which many languages make easy. I would be very interested to see another language with a rank operator, for instance. ------------------------------------------------------------------------ Challenge for you: rewrite a nontrivial program in one of those frameworks, with the following restrictions: - No iteration (including implicit iterations—map, filter; reduce is ok) -…
Rank Is actually implicitly done by numpy using a mechanism called broadcasting. For example: >>> np.array([10, 20, 30]) + np.array([[1,2,3], [4,5,6], [7,8,9]]) array([[11, 22, 33], [14, 25, 36], [17, 28, 39]]) Sieves exist in numpy, called masks: >>>np.array([10, 20, 30]) > 15 array([False, True, True]) Of course they can be operated on just like any other numpy array. Grades exist in numpy: >>>np.array([5,4,3,2,1])…
Numpy's broadcasting is scalar conformability, to which the rank operator (and general conformability) provides a general case. Example in j:
] x =. i. 2 3 4
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
16 17 18 19
20 21 22 23
] y =. i. 3 4
0 1 2 3
4 5 6 7
8 9 10 11
x + y NB. this will error because + expects that, if its arguments' shapes are not the same, one will be a prefix of the other
|length error
| x +y
NB. this is easy enough to fix, however
x +"2 y NB. +"2 is shorthand for +"2 2; meaning, choose rank-2 arrays from both the left and right arguments
0 2 4 6
8 10 12 14
16 18 20 22
12 14 16 18
20 22 24 26
28 30 32 34
Numpy will actually do this without the rank operator, because it uses suffix agreement rather than prefix agreement (which is absolutely bonkers—j used suffix agreement for about 5 minutes in 1990, before realising it was an awful idea). For for numpy, see if you can add: np.array([[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) + np.array([[0, 1, 2], [3, 4, 5]])
Intelligently. (I'm sure it's not overly difficult to come up with a solution, but can you do it with a single higher-order function call which generalises to other argument shapes?)(The j equivalent, (i. 2 3 4) + (i. 2 3) also works without trouble.)
------------------------------------------------------------------------
Another example, which may be more illustrative, is the ability to perform reductions along arbitrary axes. For example: ] x =. i. 4 3
0 1 2
3 4 5
6 7 8
9 10 11
+/ x NB. sum reduced along leading axis, the default, producing an array of shape 3
18 22 26
+/"1 x NB. sum each rank-1 array (vector); or, reduce last axis, producing an array of shape 4
3 12 21 30
------------------------------------------------------------------------
Another curiosity, which I have thus far neglected, is the extent to which numpy's being 'a little more verbose' is actually incredibly important in shaping the way you approach and think about problems. The great-uncle comment also addresses this, but Iverson probably says it better than either of us can: read https://www.jsoftware.com/papers/tot.htm