In general, we're less concerned about "the work that it's doing" in the sense of raw processor instructions, and more concerned about the semantic complexity for the programmer. So if a line says "set A to true if B or C are true", that's simple. If it says "filter array A to only include elements where this inlined lambda function returns 5 or more, and then return the results with an even index" it's a bit harder to figure out the intent behind it.
>If it says "filter array A to only include elements where this inlined lambda function returns 5 or more, and then return the results with an even index" it's a bit harder to figure out the intent behind it.
I'd argue the contrary though.
That the "semantic complexity" is less when you only keep intent-code, than when you spread it over 20 lines of boilerplate which you have to visually parse to get to the point.
Your examples are not analogous, because they do different things.
Let's make them implement the same example, Go/C/etc style and "terse" style:
array_2 := make(int64, 0)
over_five_index = 0
for i, val := range(my_array) {
if val >= 5 {
over_five_index += 1
if over_five_index % 2 == 0 {
append(array_2, val)
}
}
}
vs:
array_2 = my_array
.filter((val) => val >= 5)
.filter((_, i) => i % 2 == 0)
I don't see how there's less "semantic complexity" in the former for the programmer to parse. It's just less per line, but worse overall -- in that he has to now reconstruct the full intention from all the individual lines.