<div dir="ltr">This thread was, at first, discussing both records-specific and general approaches; the records-specific part is now being addressed in other threads, but I think the following has not yet been engaged with:<div><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 9, 2018 at 1:56 PM, Kevin Bourrillion <span dir="ltr"><<a href="mailto:kevinb@google.com" target="_blank">kevinb@google.com</a>></span> wrote:</div><div class="gmail_quote"><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><span style="font-weight:400">But I don't want to give up too easily on a more </span><b>general</b> approach that would apply to records, methods, and constructors. That's been sketched at times as</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><br></div><div style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace"> void foo(int num, String unrelated)</font></div><div style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">     requires (num >= 0) {</font></div><div style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace">   ...</font></div><div style="color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><font face="monospace, monospace"> }</font></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><br></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">where `requires` takes a boolean expression*, which lives in the same scope as the body proper; if it evaluates to false, an exception is thrown and the body is never entered.</div><div><br></div>The main criticism I hear about this is that it feels like a <b>"method with two bodies"</b>. To that I'd point out that<div><ul><li>it is only an <b>expression</b> -- and anything even moderately complex ought to be factored out, just like we advise for lambdas<br></li><li>this expression isn't implementation; it's contract, so frankly it <b>belongs </b>in this elevated place more than it does in the body. It is information that pertains, not really to the body, but to the communication between caller and body - just like the signature does.</li><li>this way, the preconditions can be <b>inherited</b> by default in an overriding method, which seems awfully convenient to me right now. (If you have some conditions you wouldn't want inherited for some reason, keep those in the regular body. I'm not sure whether these are <i>technically</i> LSP violations, but in pragmatic terms they don't seem to be, to me)<br></li></ul></div><div>I bring all this up because some of the upsides seem quite compelling to me:</div><div><ul><li>The automatically composed exception <b>message</b> will be more useful than what 90% of users bother to string together (and the other 10% are wasting time and space dealing with it).</li><li>These expressions can be displayed in generated <b>documentation</b> so you don't have to write them out a second time in prose.</li><li>I admit this may feel weird for a core language feature, but you can choose the idiomatic exception <b>type</b> automatically: if the expression involved at least one parameter, it's IAE; otherwise it's probably ISE (except in the amusing case of `requires (false)` it is UOE). (Again, maybe this is too weird.)</li><li>Some of these expressions are <b>verifiable</b> statically. For example a call to `foo(-1, "x")` (using example above) should be caught by javac. I suppose we teach it to recognize cases like empty collections through compiler plugins.</li></ul><div>Note that the other design-by-contract idioms are still addressed well enough by `assert`; we only need this one because `assert` disclaims this use case (for good reason).</div></div><div><br></div><div>(*why I say it should take one boolean expression, not a comma-separated list: I think we might as well let the user choose between short-circuiting or not, by using && and & directly, which makes it clear to readers as well. Well, that is, charitably assuming that reader remembers the difference.)</div></div></blockquote><div><br></div><div> </div></div>-- <br><div class="m_-561374062706986226m_2357550776840181181gmail-m_9123446196020554738gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div style="line-height:1.5em;padding-top:10px;margin-top:10px;color:rgb(85,85,85);font-family:sans-serif"><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(213,15,37);padding-top:2px;margin-top:2px">Kevin Bourrillion |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(51,105,232);padding-top:2px;margin-top:2px"> Java Librarian |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(0,153,57);padding-top:2px;margin-top:2px"> Google, Inc. |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(238,178,17);padding-top:2px;margin-top:2px"> <a href="mailto:kevinb@google.com" target="_blank">kevinb@google.com</a></span></div></div></div></div></div></div></div>
</div></div></div>