[1, 2, 3].map(a => a * 10)
if I wanted to literally carry out that task alone. [[0, 1, 2],
[3, 4, 5],
[6, 7, 8]].flatMap(a => a * 10) scala> Array(Array(1,2),
Array(4,5)).flatMap(a => a * 10)
^
error: value * is not a member of Array[Int]
You would need to write it like this: scala> Array(Array(1,2),
Array(4,5)).flatMap(a => a.map(x => x * 10))
But then you'd get a flattened array of ints, not array of arrays of ints: res6: Array[Int] = Array(10, 20, 40, 50)
So to get the same result as (i. 2 2) * 10
You'd need to write: scala> Array(Array(1,2),
Array(4,5)).map(a => a.map(x => x * 10))
res7: Array[Array[Int]] = Array(Array(10, 20), Array(40, 50))
...which is more verbose, no? :) EDIT: obviously, I mean "map in map" part, not the Array initialization!The problem with list comprehensions and `map`, `filter` and friends is that they work very well for flat lists, or lists of lists in some specific circumstances (ie. when you can use `flatMap`). 2D arrays in the general case, and arrays with higher dimensions are really hard to work with using these primitives, unless you have some clever overloads, like what Clojure does. I think Haskell also has a solution for this, but I don't know it enough to comment further, unfortunately :)
1 2 3 4 5
6 7 8
I.e. 5 elements and 3 elementsOther possibilities include:
(*) extending the length of the short array to match the length of the long array -- padding with zeros on the right -- before adding.
(*) finding all possible sums between pairs with one number from one array and the other number from the other array.
(*) cyclically extending the shorter array (probably not useful in this example, but since the example didn't come with a use case that's difficult to know for sure).
(*) Treating each array as a decimal number (or a number in some other base)
(*) combining the two array as a single list of numbers and summing everything to a single value
and... so on...
One point being that programming languages support arbitrarily complex operations.
Another point being that "sum" in this context carries some understandable ambiguity -- the sort of thing which we usually try to constrain with use cases or examples or similar elaboration.
1 2 3 + 4 5 6 7
|length error
| 1 2 3 +4 5 6 7
In general - depends on the operation. Sometimes the verb checks that both operands have the same rank and dimensions, sometimes the shorter/smaller side gets applied column-wise (or cell-wise/page-wise): (2 2 $ 1 2 3 4) NB. $ means "reshape"
1 2
3 4
(2 2 $ 1 2 3 4) + 1 2
2 3
5 6
Sometimes the shorter side is repeated as much as needed to get the correct length, and sometimes the shorter side gets extended with 0s, and sometimes the longer side gets truncated: (2 2 $ 1 2 3 4 5 6)
1 2
3 4
(2 4 $ 1 2 3 4 5 6)
1 2 3 4
5 6 1 2
To be perfectly honest: it's very unintuitive to me and I have to check the docs pretty often to see how the given verb behaves outside of the simplest case (ie. when the rank and dimensions match). But, I learned J as a hobby and never invested enough time into it to really learn all the built-ins, nor did I try using J outside of toy examples, so maybe this behavior becomes convenient once you internalized it?EDIT: forgot to mention, you can also control the effective rank of the verb, like this:
<"0 (2 2 $ 1 2 3 4)
┌─┬─┐
│1│2│
├─┼─┤
│3│4│
└─┴─┘
<"1 (2 2 $ 1 2 3 4)
┌───┬───┐
│1 2│3 4│
└───┴───┘
<"2 (2 2 $ 1 2 3 4)
┌───┐
│1 2│
│3 4│
└───┘
the `<` verb means "box", without the `"n` part you'd get the last value, which is a 1-dimensional array of boxes of length 1 (with 2x2 array inside the box). By selecting rank of the verb, you can decide on which level the verb should be applied: with `"0` it's applied to the smallest possible chunks of the array (cells - you get 2x2 array of boxes), with `"1` you apply the verb to bigger chunks (rows), and so on, for input arrays of any dimensions (so if you have a 3x2x2 array, `"2` will apply the verb to the 3 2x2 arrays).