Mapped operators
SPL takes inspiration from Matlab and supports auto-vectorization or mapping of expression operators to work over lists and maps.
There are two kinds of mapped operators: non-dotted and dotted. Non-dotted binary operators such as *, +=, or - are mapped if one operand is a scalar and the other a list or map. Here are some examples:
void test() {
mutable list<int32> ls = [1, 2, 3];
ls = 2 * ls; // 2 * [1, 2, 3] == [2, 4, 6]
ls += 2; // [2, 4, 6] + 2 == [4, 6, 8]
ls = ls - 1; // [4, 6, 8] - 1 == [3, 5, 7]
mutable map<rstring, int32> mp = {"x":1, "y":2};
mp = 2 * mp; // 2 * {"x":1, "y":2} == {"x":2, "y":4}
mp += 2; // {"x":2, "y":4} + 2 == {"x":4, "y":6}
mp = mp - 1; // {"x":4, "y":6} - 1 == {"x":3, "y":5}
}
SPL also supports dotted mapped operators such as .+ or .*. If both operands are equal-length lists or maps with the same key set, the dotted operators work on corresponding pairs of elements at a time. For example:
[3,2] .* [5,4] == [3*5, 2*4] == [15,8] // multiply two lists
{"x":4, "y":6} .- {"x":3, "y":1} == {"x":1, "y":5} // subtract two maps
If the operands are lists of different sizes or maps with different key sets, the mapped operator triggers a runtime error. Dotted operators have the same precedence as their non-dotted counterparts.
| Dotted operators | Description |
|---|---|
| .* ./ .% | Mapped multiplication, division, remainder |
| .+ .- | Mapped addition, subtraction |
| .<< .>> | Mapped bitwise left-shift, right-shift |
| .< .<= .> .>= .!= .== | Mapped comparison |
| .& | Mapped and |
| .^ | Mapped xor |
| .| | Mapped or |
Mapped operators unwrap only a single dimension. For example, 2 * [[1,2],[3,4]] is not supported, and neither is [[1,2],[3,4]] .* [[5,6],[7,8]], because they both must unwrap multiple dimensions of lists before the operators are applicable.