3 ms·
In the case we’d need a little context of what the map, filter, and find operations are, but if map is multiple by 2 and filter is less than 200 you can just re
by twobitshifter 6y ago
In the case we’d need a little context of what the map, filter, and find operations are, but if map is multiple by 2 and filter is less than 200 you can just replace the filter and map with a single if in the for loop that performs the multiplications and check and return immediately when you find X. That’s pretty obvious, always takes only one run, doesn’t reallocate, and doesn’t add concepts, which is of course adding complexity.
- stouset 6y agoYes and we could replace all of that with an implementation in assembly which both compiles and runs faster. But we don't do that because for the entire history of computing, we've come to realize that abstractions enable us to reason about programs at a higher level without having to be bogged down in irrelevant details and that getting those details right once lets us avoid the inevitable bugs that occur while reimplementing them thousands of times. By absolutely every objective measure we know in software engineering let triples = ints.map(|x| x * 3) is strictly superior to var triples = []int for value := range ints { triples = append(triples, value * 8) } The fact that this even has to be argued is just bonkers to me. The second one is trivial to introduce bugs into, reading it requires mentally filtering out 90% of the code as irrelevant minutiae, and it's even worse from a performance perspective unless you remember each and every time to allocate a result array of the appropriate length to avoid reallocation. None of the details of allocating a result array or iterating over indices/values are important from the purpose of expressing the problem to be solved, and yet every time someone has to read this solution those things are of greater visibility than the actual business logic. Worse, repetitive and unnecessary boilerplate like this hides bugs. Did you catch the fact that I'm multiplying by the wrong value in the golang version? Did you catch that I'm accidentally tripling the indices and not the values themselves? If you did, would you at least acknowledge that the first bug is much easier to identify in the first example than the second, and that the second bug is strictly impossible? As an added bonus, the first one (in Rust at least) is automatically vectorized using SIMD for optimal performance. This happens even as you chain additional operations to arbitrary complexity. If you still somehow think the second version is "better", then whatever your argument is can trivially be repurposed to say this version is better still: int* triples = malloc(sizeof(int) * array_len); for (int i = 0; i < array_len; i++) { triples[i] = array[i] * 3; } If those details of creating a result array and explicitly enumerating are important, why isn't maintaining your own counter and directly indexing? At least the C version somewhat encourages you to allocate a result array of the correct size.