<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">On Feb 22, 2016, at 2:52 PM, Joe Groff via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">However, this is problematic for `mutating` methods. Since the first argument is `inout`, the mutation window for the parameter formally ends before the second argument can be applied to complete the call. Currently we miscompile this, and form a closure over a dangling pointer, leading to undefined behavior:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">struct Bar {</div><div class=""> var x = 0</div><div class=""> mutating func bar() { x += 1 }</div><div class="">}</div><div class=""><br class=""></div><div class="">let bar = Bar.bar</div></blockquote></div></div></div></div></div></blockquote><div><br class=""></div><div>Wow, I thought we were banning this, along with the other unsupported partial application cases. I’d strongly suggest doing that *now* (independently of how the design topic is resolved) since it is such an open tar pit.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">We can close this hole by disallowing a reference to Bar.bar, like we already disallow partial applications. However, I think it would be in line with our other simplifications of the function type system to change the type of `Bar.bar` and other unapplied instance method references to no longer be curried. </div></div></div></div></div></blockquote><div><br class=""></div><div>I see a few possible design points:</div><div><br class=""></div><div>1. Disallow partial application of mutating methods.</div><div>2. Change all partially applied methods to be an uncurried form (as you propose).</div><div>3. Change mutating methods to be uncurried, but leave everything else curried.</div><div>4. Change methods on structs/enums(protocols?) to be uncurried, but leave classes curried.</div><div><br class=""></div><div>#1 is the safe path.</div><div>#2 is the nuclear path.</div><div>#3/#4 are the weirdly inconsistent paths.</div><div><br class=""></div><div>None of these are really great. Since you’re advocating for it, I’m very concerned about making partially applied methods be uncurried always (#2). I have seen a *lot* of people use curried methods on classes (in particular) and this leads to some pretty elegant patterns. I’d expect any serious discussion of changing this behavior to include a survey of what people are actually using this for, and whether the end result we’d get from this change would be better or worse overall (not just in a single case).</div><div><br class=""></div><div>-Chris</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">In addition to providing a model for unapplied instance methods that works with mutating methods, this would also eliminate a type difference between free functions and methods of the same arity, allowing for easier code reuse. For instance, `reduce` takes a closure of type (State, Element) -> State. Flattening the formal type of instance methods would allow binary methods to be used as-is with `reduce`, like binary free functions can:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">func sumOfInts(ints: [Int]) -> Int { </blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""> return ints.reduce(0, combine: +)</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">}</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">func unionOfSets<T>(sets: [Set<T>]) -> Set<T> { <br class=""> return ints.reduce([], combine: Set.union)<br class="">}</blockquote><div class=""><br class=""></div><div class="">What do you all think?</div><br class=""><div class="">-Joe</div></div></div></div></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>