Iterative Assignment

This proposal was inspired by the Julia programming language.
In this language, there are several operators for easily manipulating arrays.
we can use:
.+ .- .* ./ .% .^ etc.
and their compound assignment versions:
.+= .-= .*= ./= .^= etc.

I would like to generalise this and propose a generalised compound iterative assignment operator(.=)

It works a bit like map / forEach

syntax:

/** Iterative Assignment **/

let arr = [1, 2, 3, 4]
arr .= ([k, v]) => v + 1

let obj = { a: 1, b: 2, c: 3, d: 4 }
obj .= ([k, v]) => v + 1

console.log(arr)
// [ 2, 3, 4, 5 ]

console.log(obj)
// { a: 2, b: 3, c: 4, d: 5 }

currently this operator can simplify the follow common and tedious code.

let arr = [ 1, 2, 3, 4 ],
fn = f => arr.map( (v, k) => f(k, v) )
arr = fn( (k, v) => v + 1 )

let obj = { a: 1, b: 2, c: 3, d: 4 }
fn = f => {
    let pairs = []
    for( [k, v] of Object.entries(obj) )
        pairs.push( f(k, v) )
    return Object.fromEntries( pairs )
}
obj = fn( (k, v) => [ k, v + 1 ] )

console.log(arr)
// [ 2, 3, 4, 5 ]

console.log(obj)
// { a: 2, b: 3, c: 4, d: 5 }

What are the pros and cons of this??
What do you guys think of this idea??

Would the left-side be limited to Array and Object, or would other collections be allowed like TypedArray, Map, Set etc?

I guess anything that has a key and a value would work. i.e iterables

Here's some more background on this proposal, based on what I understand of these dot operators in Julia:

Element-wise operators such as .* are found in statistical-focused languages such as Julia, R, and MatLab, and allow one to operate on each element of a vector or matrix.

i.e., if .* were added to javascript, it would look something like this (javascript doesn't really have a notion of row and column vectors, so there's multiple ways to make this interpretation):

// Multiplying two "row" vectors
[1, 0, 3] .* [2, 3, 7] // [2, 0, 21]
// Multiplying two "column" vectors
[[1], [0], [3]] .* [[2], [3], [7]] // [[2], [0], [21]]
// Multiplying two matricies
[[1, 2], [3, 4]] .* [[2, 3], [4, 5]] // [[2, 6], [12, 20]]
// Multiplying a row and a column vector to produce a matrix
[1, 2] .* [[1], [2]] // [[1, 2], [2, 4]]
// Multiplying a vector with a scalar
[1, 2] .* 3 // [3, 6]

If I understand this proposed generalized operator correctly, it's mostly a .map() followed by an assignment. If this is the case, I presume this proposal is mostly focussing on the last case - operating on a vector with a scalar, as a .map() by itself doesn't have the power to do any of the other tasks.

As javascript isn't designed to be a statistical language, most websites don't need that kind of power, I feel like statistical functionality is best suited for external libraries - meaning, I wouldn't want to copy over operators such as ".*" verbatum into javascript. however, if there is something useful to be gleaned from these statistical languages, that can be adapted to work in a general-purpose way, then it's worth considering.

2 Likes

The iterator protocol is a common way to read values from objects; there is no common protocol to add or change them. Arrays have push, Maps have set, Sets have add, strings are immutable (or have + or concat), etc.

Iā€™m also very skeptical of the claim that this kind of code is common.

1 Like

I am, too, though it's worth noting the broad use of lenses in Haskell that more or less fill exactly this role and their limited use in JS as well.

Funny that there are nothing to focus in JS :joy: :joy:

Lenses aren't exactly a built-in thing in Haskell, either. :wink: