<div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;">So, a further thing to keep in mind is that currently, adding fields to records is not even source compatible to begin with. For example, if we have
<div><br>
</div>
<div> record Point(int x, int y) { }</div>
<div><br>
</div>
<div>And a client uses it in a pattern match:</div>
<div><br>
</div>
<div> case Point(int x, int y): </div>
<div><br>
</div>
<div>And then we add an `int z` component, the client will break. (When we are able to declare deconstruction patterns, such a migration could include an XY pattern as well as constructor, but we are not there yet.) </div></div></blockquote><div><br></div><div>To be honest, I didn't think of that scenario. So, thank you for making me more alert to potential issues.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;"><div>
</div>
<div>I think your mail rests on the assumption that it should be fine to modify records willy-nilly and expect compatibility without a recompile-the-world, but I think this is a questionable assumption. Records will likely have features that ordinary
classes do not yet have access to for a while, making such changes risky. </div></div></blockquote><div><br></div><div>While I would love to be "willy-nilly", in this issue that is not really my concern. Because I'm just considering the following scenarios:</div><div><br></div><div>Scenario A: After changing the dependency, the dependent code is binary compatible, and compiles fine, but does something else than before the change.</div><div><br></div><div>Scenario B: After changing the dependency, the dependent code is binary compatible, and fails to compile.</div><div><br></div><div>Scenario C: We had shadowing in the original code, and none of the above happened.</div><div><br></div><div>Obviously we have to make an assumption that there is a naming ambiguity one way or the other, otherwise there is no difference between shadowing or compile time error.</div><div><br></div><div>I think I'm uncontroversial by stating that scenario A is far more damaging than scenario B. And also that scenario C is considerably more likely than the other events.</div><div><br></div><div>So, the question is if scenario C gains enough to allow for scenario A to happen, which is the opinionated part of course. I would say that scenario C almost always hurts readability. As someone might fail to notice the ambiguity. Failing to notice it can be quite likely given that the existence of the property shadowing the local variable (or field for that matter) is not apparent (assuming that the declaration of the record is not very close). So, someone reading such a code has a decent likelihood to conclude that the variable is the local variable being shadowed, when in fact it is the property of the record. While an IDE might color code this (though I would guess they would both be considered local variable by the IDE), but regardless what an IDE might do, I tend to read code in the browser a lot (and I would assume I'm not alone), because I'm just lazy to clone the repo (etc).</div><div><br></div><div>Now one could argue that shadowing would be beneficial in some cases for lambda parameters, so why not here? But I think the situation is different. The main reason why the lack of shadowing is sometimes bothersome in lambda, is because there are quite a few methods taking an argument, and then passing the same to the lambda (a'la `Map.computeIfAbsent`). That is, the main thing is that it is beneficial, because we know that the variable being shadowed has the same value as the lambda parameter. I don't think this would be anywhere near as common for withers, because not only do we need to have the property have the same value as the shadowed variable (which I think is already unlikely), but we would need to use that value within the withers. Not only this, but in case of lambda we always want to use the lambda parameters over the local to save the cost of capturing the local variable (for no reason). However, in case of withers, we have a simple workaround for the rare case of unavoidable conflict: We can just access that property via the source record (which should have the same performance).</div><div><br></div><div>An additional argument for the preference of compile time error over shadowing is that if shadowing is chosen for the final version, then there is no going back (even if it laters turns out to be a mistake), while in case compile time error is chosen, there is still an opportunity to introduce shadowing later.</div><div><br></div><div>So, my conclusion is that compile time error is a far more preferable behavior over shadowing.</div><div><br></div></div></div>