<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><blockquote type="cite" class="">On Dec 8, 2015, at 3:52 PM, Amir Michail via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class="">Swift is a safe language after all. Moreover, it is all too easy to accidentally type “assert” when you mean “precondition”.</blockquote><div class=""><br class=""></div><div class="">Here’s some rationale that may be missing. The two functions have distinct roles:</div><div class=""><br class="">- assert: checking your own code for internal errors.<br class="">- precondition: for checking that your clients have given you valid arguments.<br class=""><br class="">It’s actually important to distinguish these two cases because the second one demands public documentation while the first does not.<br class=""><br class="">For example: in Swift’s standard library we promise never to allow memory errors unless you call (Obj)C code or use an explicitly labeled “unsafe” construct. On the occasions where we need to do a check on the client’s parameters to avoid causing a memory error when we’re given invalid arguments, we document the requirements on the arguments as a precondition, and use (our equivalent of) precondition() to check it. We also have a bunch of internal sanity checks to make sure our assumptions about our own code, where the type system doesn’t already guarantee them, are correct. For those, we use (our equivalent of) assert(), because we don’t want to slow down *your* code as an artifact of our development process (the use of sanity checks).<br class=""><br class="">Here are a couple of concrete examples:<br class=""><br class=""><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class="">/// A collection whose elements are all identical `Element`s.</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class="">public struct Repeat<Element> : CollectionType {</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> ...</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> /// Access the element at `position`.</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> ///</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> /// - Requires: `position` is a valid position in `self` and</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> /// `position != endIndex`.</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> public subscript(position: Int) -> Element {</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> _precondition(position >= 0 && position < count, "Index out of range")</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> return repeatedValue</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> }</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class="">}</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""><br class=""></font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class="">extension String.UTF8View {</font></div><div class="" style="font-family: AvenirNext-Regular;"><font face="Menlo" class=""> ...</font></div><div class="" style="font-family: AvenirNext-Regular;"><div class=""><span class="" style="font-family: Menlo;"><br class=""></span></div><div class=""><span class="" style="font-family: Menlo;"> private func _encodeSomeContiguousUTF16AsUTF8(i: Int) -> (Int, UTF8Chunk) {</span></div><div class=""><font face="Menlo" class=""> _sanityCheck(elementWidth == 2)</font></div><div class=""><font face="Menlo" class=""> _sanityCheck(!_baseAddress._isNull)</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> let storage = UnsafeBufferPointer(start: startUTF16, count: self.count)</font></div><div class=""><font face="Menlo" class=""> return _transcodeSomeUTF16AsUTF8(storage, i)</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class="">}</div></div><div class="" style="font-family: AvenirNext-Regular;"><br class=""></div><div class="" style="font-family: AvenirNext-Regular;"><div class=""><div class="">In the first example, we have a precondition that the client doesn’t index past the end of the collection. In this case we’re not strictly bound to check it because we’re not avoiding a memory error,* but we do check it as a service to our clients; it will help them find their bugs sooner.</div><div class=""><br class=""></div><div class="">In the second example, this is a private function that is meant to be called only on a code path where we’ve ensured elementWidth == 2 and _baseAddress is not null (_sanityCheck is the stdlib’s equivalent of assert). That is in fact how it is being used, but we want to ensure that ongoingly. For example, we don’t want someone to add code later that uses it incorrectly. Since we run our tests in both debug and release and we have decent test coverage, the assertions are very likely to fire if that should happen.</div><div class=""><br class=""></div><div class="">You might think from the above that assert() only gets used in private methods and precondition() only gets used in public methods, but that’s not the case; you could inline any private method into the body of the public method it implements, and doing sanity checks there would still make sense. Precondition checks occasionally appear in private methods, too. The simplest example is where duplicated precondition checking code is factored out of a bunch of public methods and into a single private helper. </div><div class=""><br class=""></div><div class=""><div class="">Hope this helps,</div><div class="">Dave</div><div class=""><br class=""></div><div class="">* <span class=""> </span><font face="AvenirNext-Regular" class="">Note that some preconditions actually can’t be checked, so having a rule that all preconditions must be checked isn’t tenable.</font></div></div><div class=""><font face="AvenirNext-Regular" class=""><br class=""></font></div></div></div></div></body></html>