<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 Jan 16, 2017, at 6:42 PM, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><div><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">on Mon Jan 16 2017, Charles Srstka <</span><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">> wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class="">On Jan 16, 2017, at 7:49 AM, Chris Eidhof via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class="">Hi,<br class=""><br class="">How does everyone feel about adding a second version of `reduce` to<br class=""></blockquote><br class=""><blockquote type="cite" class="">`Sequence`? Instead of a `combine` function that's of type `(A,<br class="">Element) -> A`, it would be `(inout A, Element) -> ()`. This way, we<br class="">can write nice functionals algorithms, but have the benefits of<br class="">inout (mutation within the function, and hopefully some copy<br class="">eliminations).<br class=""><br class="">IIRC, Loïc Lecrenier first asked this on Twitter. I've been using it<br class="">ever since, because it can really improve readability (the possible<br class="">performance gain is nice, too).<br class=""><br class="">Here's `reduce` with an `inout` parameter, including a sample:<br class=""><a href="https://gist.github.com/chriseidhof/fd3e9aa621569752d1b04230f92969d7" class="">https://gist.github.com/chriseidhof/fd3e9aa621569752d1b04230f92969d7</a><br class=""><br class="">--<span class="Apple-converted-space"> </span><br class="">Chris Eidhof<br class=""></blockquote><br class="">I did this in my own private code a while ago. There is one drawback, which is that Swift’s type<br class="">inference system isn’t quite up to handling it. For example, doing this results in an “ambiguous<br class="">reference to member” warning:<br class=""><br class="">range.reduce([Int]()) { $0.append($1) }<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">The diagnostic could be better, but the compiler shouldn't let you do</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">that, because it requires passing an unnamed temporary value ([Int]())</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">as inout.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>No it doesn’t. The signature of the method is:</div><div><br class=""></div><div><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">func</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class=""> </span><span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">reduce</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class=""><</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">A</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class="">>(</span><span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">_</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class=""> </span><span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">initial</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class="">: A, </span><span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);"><span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">combine</span></span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class="">: (</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">inout</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class=""> A, </span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">Iterator</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class="">.</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">Element</span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class="">) </span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">-></span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class=""> ()) </span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);">-></span><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class=""> A</span></div><div><span style="color: rgb(51, 51, 51); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-variant-ligatures: normal; orphans: 2; white-space: pre; widows: 2; background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div><span style="font-variant-ligatures: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255);" class=""><span style="orphans: auto; widows: auto;" class="">The unnamed temporary value is “initial” here, which is not passed as inout; the inout parameter is the first argument to the “combine” closure. The value represented by the ‘initial’ parameter is passed to the closure, true, but only after being stored in a not-unnamed ‘var’ variable, as you can see from the source of the proposed method:</span></span></div><div><br class=""></div><div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> reduce<A>(</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> initial: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">A</span><span style="font-variant-ligatures: no-common-ligatures" class="">, combine: (inout </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">A</span><span style="font-variant-ligatures: no-common-ligatures" class="">, Iterator.Element) -> ()) -> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">A</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> result = initial</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">for</span><span style="font-variant-ligatures: no-common-ligatures" class=""> element </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">in</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">self</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> combine(&result, element)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> result</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span style="background-color: rgb(255, 255, 255);" class="">Therefore, I don’t understand this objection.</span></span></div></div><br class=""><blockquote type="cite" class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">One would think that the type of this closure should be clear:<br class=""><br class="">1) The closure calls append(), a mutating function, so $0 must be inout.<br class=""><br class="">2) The closure doesn’t return anything, which should rule out the<br class="">default implementations of reduce,<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">The closure *does* return something: (), the empty tuple</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>But it’s not what it’s supposed to return. Sequence’s implementation of reduce, which the compiler thinks matches the above, is declared like this:</div><div><br class=""></div><div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">public</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> reduce<Result>(</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> initialResult: Result, </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> nextPartialResult: (Result, </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Self</span><span style="font-variant-ligatures: no-common-ligatures" class="">.Iterator.Element) </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">throws</span><span style="font-variant-ligatures: no-common-ligatures" class=""> -> Result) </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">rethrows</span><span style="font-variant-ligatures: no-common-ligatures" class=""> -> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Result</span></div></div><div><br class=""></div>The closure is supposed to return Result, which in this case would be [Int]. It doesn’t, so I’m not sure why the compiler is thinking this is a match.</div><div><br class=""></div>Charles<div class=""><br class=""></div></body></html>