<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 29, 2015, at 8:55 PM, Kevin Ballard via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">


<title class=""></title>

<div class=""><div class="">An alternative solution is to do what Rust and C++ do, which is to use RAII. Which is to say, instead of introducing a new language construct that's explicitly tied to a scope, you just use a struct to represent the resource that you hold (e.g. a File that represents an open file). Of course, this does require some changes to structs, notably the addition of a deinit. And if structs have a deinit, then they also need to have a way to restrict copies. This is precisely what Rust does; any struct in Rust that implements Drop (the equivalent to deinit) loses the ability to be implicitly copied (a second trait called Clone provides a .clone() method that is the normal way to copy such non-implicitly-copyable structs).</div></div></div></blockquote><div><br class=""></div><div>deinit doesn't make sense for value types. Classes already support deinit, and you can use withExtendedLifetime to bound the lifetime of a resource-holding class. It would be reasonable to have a scoped lifetime marker similar to ObjC ARC too.</div><div><br class=""></div><div>-Joe</div><br class=""><blockquote type="cite" class=""><div class=""><div class="">
<div class="">This solution is elegant for a few reasons:<br class=""></div>
<div class="">&nbsp;</div>
<div class="">1. Once you allow deinit on structs (which is useful) and deal with the fact that structs are no longer implicitly copyable (because almost all deinit functions on structs won't work right if they're called twice, such as on two copies), then RAII just sort of falls out of all of this and doesn't require any specific language features.<br class=""></div>
<div class="">2. It's more flexible, because you can actually return the RAII value from a scope in order to extend its lifetime.<br class=""></div>
<div class="">3. The RAII value itself provides the means to access the resource it's protecting; e.g. a Lock might return a LockGuard RAII value from the .lock() method, and LockGuard provides the means to access the protected value (as opposed to just having the lock sitting next to the value, which makes it trivially easy to accidentally access the value without holding the lock).<br class=""></div>
<div class="">4. In Rust, this pattern also integrates extremely well with Rust's lifetime system (the system that prevents data races / memory corruption at compile time), because e.g. a LockGuard contains the lifetime of the Lock, which prevents you at compile-time from attempting to lock the Lock while you already have it locked (though it doesn't prevent deadlocks where you and another thread try and lock two locks in opposite orders, but there is plenty of stuff it does catch).</div>
<div class="">&nbsp;</div>
<div class="">The biggest problem with adding deinit to structs in Swift right now is the fact that we don't have references, which means you can't take a RAII struct and pass it to another function without losing it. Heck, you can't even call a method on it, because `self` on non-mutating methods in Swift is a value and not a reference (although we could hand-wave that away and make `self` in non-mutating RAII methods actually be an "in" reference internally, but this kind of hand-waving doesn't work when passing the struct as an argument to another function). So we'd actually have to introduce a special "in" reference, which would be like "inout" except it doesn't actually copy it out (and is guaranteed to actually pass a pointer, although this pointer may be a pointer to a temporary). Except even that fails if you want to have a computed property that returns an existing RAII value (for example, having an Array of these things; barring optimizations, the subscript getter returns a computed value). And you can't generalize such "in" references beyond function arguments without basically providing raw C pointers. Rust's lifetime system lets them do it safely, but barring such a system, Swift can't really do this (I assume it's obvious why we don't want to start using raw C pointers everywhere).<br class=""></div>
<div class="">&nbsp;</div>
<div class="">All that said, I think this is a problem Swift needs to solve, because having non-copyable structs would be very useful. In particular, I _really_ want some way to do atomics in Swift, but the only safe way I can think of to do it requires non-copyable structs (because it's not correct to do a nonatomic read (such as a memcpy) of an atomic that's visible to other threads). I suppose you could provide a way to override how struct copies work (e.g. so you could do an atomic read of the old value), but it's rather problematic to break the assumption that struct copies are cheap.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Of course, you could model RAII with classes instead of structs, that just has the overhead of heap allocation (+ atomic reference counting) for every RAII value.</div>
<div class="">&nbsp;</div>
<div class="">-Kevin Ballard</div>
<div class="">&nbsp;</div>
<div class="">On Tue, Dec 29, 2015, at 08:02 PM, Trent Nadeau via swift-evolution wrote:<br class=""></div>
<blockquote type="cite" class=""><div dir="ltr" class=""><div class=""># Introduction<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><div class="">Add a new `Scoped` protocol and enhance the do statement to automatically call enter/exit actions on resources.<br class=""></div>
<div class="">&nbsp;</div>
<div class=""># Motivation<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Resources (e.g., locks, files, sockets, etc.) often need to be scoped to a block, where some action is taken at the start of the block and another is required at the end. Examples include locking and unlocking a lock in a critical section or closing a file at the end of a block.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Doing this manually is possible using `defer` statements among other options, but this is error prone as a `defer` can be forgotten, `lock`/`unlock` calls for two locks can be switched due to a typo, etc. Having a dedicated language construct for this common case makes it easier to read and write while making code shorter and clearer.<br class=""></div>
<div class="">&nbsp;</div>
<div class=""># Language Survey<br class=""></div>
<div class="">&nbsp;</div>
<div class="">At least three major languages have widely used statements for this use case.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">## C#<br class=""></div>
<div class="">&nbsp;</div>
<div class="">C# has the `using` statement and the associated `IDisposable` interface.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```csharp<br class=""></div>
<div class=""><div class="">using (StreamReader sr = new StreamReader(filename)) {<br class=""></div>
<div class="">&nbsp; &nbsp; txt = sr.ReadToEnd();<br class=""></div>
<div class="">}<br class=""></div>
</div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</div>
<div class="">C#'s solution only handles close/exit actions via the `IDisposable.Dispose()` method and so cannot easily be used with items such as locks; however, C# has the additional `lock` statement for that use case.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">## Java<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Java has try-with-resources and the associated `AutoCloseable` interface.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```java<br class=""></div>
<div class=""><div class="">try (BufferedReader br = new BufferedReader(new FileReader(path))) {<br class=""></div>
<div class="">&nbsp; &nbsp; return br.readLine();<br class=""></div>
<div class="">}<br class=""></div>
</div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Java's solution only handles close/exit actions via the `AutoCloseable.close()` method and so cannot easily be used with items such as locks; however, Java has the additional `synchronized` statement for that use case.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">## Python<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Python has with `with` statement and the associated `__enter__` and `__exit__` special methods that classes may implement to become a "context manager".<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```python<br class=""></div>
<div class="">with lock, open(path) as my_file:<br class=""></div>
<div class="">&nbsp; &nbsp; contents = my_file.read()<br class=""></div>
<div class="">&nbsp; &nbsp; # use contents<br class=""></div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Python's solution handles both enter and exit actions and so this one construct is usable for locks as well as resources like sockets and files.<br class=""></div>
<div class="">&nbsp;</div>
<div class=""># Proposed Solution<br class=""></div>
<div class="">&nbsp;</div>
<div class="">We add a new protocol called `Scoped` to the standard library. Types for resources that have enter/exit actions will be extended to add conformance to this protocol.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">The `do` statement will be extended to allow a new `using &lt;resources&gt;` "suffix".<br class=""></div>
<div class="">&nbsp;</div>
<div class=""># Detailed Design<br class=""></div>
<div class="">&nbsp;</div>
<div class="">The `Scoped` protocol shall be as follows:<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```swift<br class=""></div>
<div class=""><div class="">public protocol Scoped {<br class=""></div>
<div class="">&nbsp; &nbsp; func enterScope()<br class=""></div>
<div class="">&nbsp; &nbsp; func exitScope()<br class=""></div>
<div class="">}<br class=""></div>
</div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</div>
<div class="">The compiler statement will accept a new form for resources. For example,<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```swift<br class=""></div>
<div class="">do using lock, let file = try getFileHandle() {<br class=""></div>
<div class="">&nbsp; &nbsp; // statements<br class=""></div>
<div class="">}<br class=""></div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</div>
<div class="">As can be seen in the example above, the resources can be bindings that already exist (like `lock`) or can be new bindings. Bindings created with `do using` are not available outside of the scope of the `do using`. Only types conforming to `Scoped` may be using with `do using`. Use of non-conforming types will result in a compiler error.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">The above example would be syntactic sugar for the following:<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```swift<br class=""></div>
<div class=""><div class="">do {<br class=""></div>
<div class="">&nbsp; &nbsp; lock.enterScope()<br class=""></div>
<div class="">&nbsp; &nbsp; defer { lock.exitScope() }<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp; &nbsp; let file = try getFileHandle()<br class=""></div>
<div class="">&nbsp; &nbsp; file.enterScope()<br class=""></div>
<div class="">&nbsp; &nbsp; defer { file.exitScope() }<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp; &nbsp; // statements<br class=""></div>
<div class="">}<br class=""></div>
</div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</div>
<div class=""># Framework Changes / Examples<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><div class="">As an example of some real-world classes that would be useful with `Scoped`, from Foundation:<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```swift<br class=""></div>
<div class="">// Would be nice to extend the NSLocking protocol instead, but that's not supported yet.<br class=""></div>
<div class="">extension NSLock: Scoped {<br class=""></div>
<div class="">&nbsp; &nbsp; func enterScope() {<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.lock()<br class=""></div>
<div class="">&nbsp; &nbsp; }<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp; &nbsp; func exitScope() {<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.unlock()<br class=""></div>
<div class="">&nbsp; &nbsp; }<br class=""></div>
<div class="">}<br class=""></div>
<div class="">&nbsp;</div>
<div class="">extension NSFileHandle: Scoped {<br class=""></div>
<div class="">&nbsp; &nbsp; func enterScope() {}<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp; &nbsp; func exitScope() {<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.closeFile()<br class=""></div>
<div class="">&nbsp; &nbsp; }<br class=""></div>
<div class="">}<br class=""></div>
</div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</div>
<div class=""># Questions and Concerns<br class=""></div>
<div class="">&nbsp;* Bikeshedding protocol naming and scoping syntax<br class=""></div>
<div class="">&nbsp;* Should the enter and exit actions be allowed to throw errors?<br class=""></div>
<div class=""><div class="">&nbsp;</div>
<div class="">-- <br class=""></div>
<div class="">Trent Nadeau<br class=""></div>
</div>
</div>
</div>
<div class=""><img style="height:1px !important;width:1px !important;border-top-width:0px !important;border-right-width:0px !important;border-bottom-width:0px !important;border-left-width:0px !important;margin-top:0px !important;margin-bottom:0px !important;margin-right:0px !important;margin-left:0px !important;padding-top:0px !important;padding-bottom:0px !important;padding-right:0px !important;padding-left:0px !important;" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/910a1b38e6de713eadc76fd73510d92ad8566cec1daf2cf3dd87249e153f68ab/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e446751433539415b44763f643d686c444556613578497a5a61705376607370536635683646317059416d2236465560705a756147613d497368356277403565635d22364641407a75467e687a574332697c4768626e47595f66336366356d487537505666786d22364e6b4a474d4f4a40543a7e4e644262417563587e65496535416661734a584569367744314257496537566869446843337732364374354e48365766335878594b4974514740585a766c49595a4a70774f43743e6d4831683245347f493a45477d23344d23344/open" class=""><br class=""></div>
<div class=""><u class="">_______________________________________________</u><br class=""></div>
<div class="">swift-evolution mailing list<br class=""></div>
<div class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""></div>
<div class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div>
</blockquote><div class="">&nbsp;</div>

<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=RoDF4MveSEMYBIqIJA6ub1g8cOZ-2BVYvqV-2FqygPhjPn8Ik60sDXBaOw-2BCbOCpIolJBVkZ-2BAaJDPxzWL-2BeMbRK7cyp8JeSicC1qEzmcL-2Fd5giYcSkF-2FEZFfFlOZ5wbJypkC2gqsRGMLGFwsezqYW8ISJVQIHNt0-2FxOGvHRIPMI6Ino4UtBNQrvZ-2BKV0uhUiBb6uCI4XXprq7Dm6GsydrTnjhSJ5pRJ7j89VFcydg7l72k-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>


_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>