4 ms·
The example is using BigDecimal class where arithmetic operators don't work, you need to call .negate() on the object, or multiply again BigDecimal("-1"). Negat
by agilob 5y ago
The example is using BigDecimal class where arithmetic operators don't work, you need to call .negate() on the object, or multiply again BigDecimal("-1"). Negating inside a loop will give different result than multiplying at the end in return line. Nevertheless, you're adding ANOTHER operation to the line which is already complex and hard to read.
- watwut 5y agoThe exactly same thing can be said about stream version. There is no meaningful difference between the two when it comes to this change - either you do it in the middle of loop or add line for it. Except that the stream version is harder to debug and read, but more effective on potentially unlimited stream.
- agilob 5y agoYou add a new line with .map or .peek before .collect
- watwut 5y agoWhich is oh so much different then to add the new line into the imperative code? Adding new line into imperative code tend to be simple.
- agilob 5y agoFluent interfaces spread complexity of reading complex operations into multiple lines, you're squeezing everything into one line where tracking few characters change will be difficult to review, difficult to compare changes, bisect bugs (change in a complex line vs addition of a new simple line). Adding new line is simple change with no increased reading complexity. Modifying already complex line to add new operation will only increase complexity, change log of this line, making it all harder. That's all I'm saying, I'd rather read 11 simple lines, than 4 complex lines.
- watwut 5y agoI can add one new line into procedural code that does exact same thing. It wont increase reading complexity either. It wont even force me to think about what hidden map parameters. It will all be visible directly.
- setr 5y agoA new .map line has limited scope of access, and thus highly restricted possibilities. The same line in a for-loop can access anything, including things from other lines. The primary benefit of these kinds of functional chains is that each step is highly constrained in their capabilities, mainly by their function name and access scope, so you can better verify that it really does do what it says on the tin. A for loop’s content has to be ultimately read thoroughly, because anything goes. Including modifying lists unrelated to the list under question.
- watwut 5y agoThe price for that limited scope is that it is much harder to figure out what is actual parameter of lambda that goes into map function. If is also not even limited all that much. In lambda, everything from surrounding scope is visible too. My personal issue with these is that it is all harder to reason about, harder to read, harder to debug. And each time there is real issue, I have to unpack these into procedural, fix and then encrypt again. I dont see less bugs in code since we started using these. Bugs did not dropped.
- setr 5y ago> The price for that limited scope is that it is much harder to figure out what is actual parameter of lambda that goes into map function I’m not sure why that soul would be the case... it’s whatever came out of the previous action? You’re doing list operations...always. Nested list operations get convoluted fast, so I generally avoid them (break them up into separate iterations) but otherwise. The only thing I can remember complicating things is issues with type conversion, but the IDE usually tells you what’s up. The loss of print debugging and useful debugger support is a pain but usually resolved by commenting out half the manipulations and printing immediately. Otherwise IME it’s a lot simpler to see a series of independent operations on the total list, then it is to follow a for loop interacting with one element at a time. But personally I switch between the two styles freely, depending on which one is “cleaner” so I likely naturally avoid the more convoluted/difficult cases.