<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="">+1<div class=""><br class=""></div><div class="">I think it's a very interesting proposal and here is why:</div><div class=""><br class=""></div><div class="">- It improve readability by expressing intent.</div><div class="">For example the difference between those two function, just by their signature, is obvious:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> update(</span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> m: </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Class</span><span style="font-variant-ligatures: no-common-ligatures" class="">) -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Class</span></div></div><div class=""><br class=""></div><div class="">and</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> update(</span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> m: </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Class</span><span style="font-variant-ligatures: no-common-ligatures" class="">) =&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Class</span></div></div><div class=""><br class=""></div><div class="">The first one mutates the class passed in argument and returns it (for example, to allows chaining mutable methods).</div><div class="">And the second one returns a new reference without touching the original class passed in argument.</div><div class="">Or at least that is how I would expect it to work. (Maybe OP can confirm?)</div><div class=""><br class=""></div><div class="">- Though the compiler helps with captures it would give an additional safeguard again accidentally capturing the context or creating reference cycles.&nbsp;</div><div class="">For example, it could allow to define pure closures that escape their scope, without having them be marked @escaping:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> updater(fn: (</span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">) =&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">, initial: </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">) -&gt; () -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</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="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> i = 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="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</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="">&nbsp; &nbsp; &nbsp; &nbsp; i = fn(i)</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="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> i</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="">&nbsp; &nbsp; }</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><div class="">instead of</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> updater(fn: </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">@escaping</span><span style="font-variant-ligatures: no-common-ligatures" class=""> (</span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">) -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">, initial: </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">) -&gt; () -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> i = initial</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; i = fn(i)</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> i</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; }</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div></div></div><div class=""><br class=""></div><div class="">This would introduce some pretty interesting scoping rules, I'd be very interested to hear your opinion on this.</div><div class=""><br class=""></div><div class="">- *something something Stream Fusion*</div><div class=""><br class=""></div><div class="">André</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 16 Feb 2017, at 19:10, Ross O'Brien 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=""><div dir="ltr" class="">I'm in favour of 'pure' functions, because they're a way of reducing the repetition of the kind of calculations you might want to perform in initialisers to convert argument values into property values.<div class=""><br class=""></div><div class="">I don't know why "the function must have a return type" is seen as a requirement, though. There may not be many reasons to call a pure function without a return type, but requiring a return type, or disallowing inout parameters, seems arbitrary to me.</div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Thu, Feb 16, 2017 at 5:51 PM, Robert Widmann via swift-evolution <span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><br class=""></div><br class=""><div class=""><span class=""><blockquote type="cite" class=""><div class="">On Feb 16, 2017, at 12:30 PM, Rien via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_4197988501921103072Apple-interchange-newline"><div class=""><div class="">In essence this is about assistance from the compiler that a function marked ‘pure’ is indeed pure?<br class="">I.e. an error message should be generated when a function marked as ‘pure’ is in fact not ‘pure’?<br class=""><br class="">If the answer to both questions is ‘yes’ then -not surprising- its a -1 from me.<br class=""><br class="">Unless there are other benefits?<br class=""></div></div></blockquote><div class=""><br class=""></div></span><div class="">This feature<a href="https://github.com/apple/swift/blob/master/docs/proposals/OptimizerEffects.rst" target="_blank" class=""> already exists</a>&nbsp;in a certain sense - via the @effects annotation - but is undocumented, highly unstable, and does not entail any semantic checking.&nbsp; I think that at least indicates a desire, even if it’s only in the lower-level parts of SIL now, to have some way to determine the “purity” of a function to perhaps guide an inliner or future block fusion pass.&nbsp; Perhaps Andrew Trick can speak more about the goals of the annotation and whether it would be ready for prime time as it were. &nbsp;</div><div class=""><div class="h5"><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">Regards,<br class="">Rien<br class=""><br class="">Site: <a href="http://balancingrock.nl/" target="_blank" class="">http://balancingrock.nl</a><br class="">Blog: <a href="http://swiftrien.blogspot.com/" target="_blank" class="">http://swiftrien.blogspot.com</a><br class="">Github: <a href="http://github.com/Balancingrock" target="_blank" class="">http://github.com/<wbr class="">Balancingrock</a><br class="">Project: <a href="http://swiftfire.nl/" target="_blank" class="">http://swiftfire.nl</a><br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><blockquote type="cite" class="">On 16 Feb 2017, at 18:03, T.J. Usiyan via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""># Pure Functions<br class=""><br class="">* Proposal: [SE-NNNN](<a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md" target="_blank" class="">https://github.com/<wbr class="">apple/swift-evolution/blob/<wbr class="">master/proposals/NNNN-name.md</a>)<br class="">* Author(s): [TJ Usiyan](<a href="https://github.com/griotspeak" target="_blank" class="">https://github.com/<wbr class="">griotspeak</a>)<br class="">* Status: **Awaiting review**<br class="">* Review manager: TBD<br class=""><br class="">## Introduction<br class=""><br class="">Some functions are, essentially, only meant to be transformations of their input and–as such–do not and should not reference any variables other than those passed in. These same functions are not meant to have any effects other than the aforementioned transformation of input. Currently, Swift cannot assist the developer and confirm that any given function is one of these 'pure' functions. To facilitate this, this proposal adds syntax to signal that a function is 'pure'.<br class=""><br class="">'pure', in this context, means:<br class="">1. The function must have a return value<br class="">1. This function can only call other pure functions<br class="">1. This function cannot access/modify global or static variables.<br class=""><br class="">## Motivation<br class=""><br class="">Consider the following example where `_computeNullability(of:)` is meant to create its output solely based on the provided recognizer.<br class=""><br class="">```<br class="">class Recognizer {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>var nullabilityMemo: Bool?<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>var isNullable: Bool {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>func _computeNullability(of recognizer: Recognizer) -&gt; Bool {…}<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>if let back = nullabilityMemo {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>return back<span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>} else {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>let back = &nbsp;_computeNullability(of: self)<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>nullabilityMemo = back<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>return back<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>}<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>}<br class="">}<br class="">```<br class="">if `_computeNullability(of:)` is recursive at all, there exists a real potential to accidentally reference `self` in its body and the mistake, depending on circumstance, can be terribly subtle. Converting `_computeNullability(of:)` to a `static` function is an option but obfuscates the fact that it is *only* to be called within `isNullable`.<br class=""><br class=""><br class="">## Proposed solution<br class=""><br class="">Given the ability to indicate that `_computeNullability(of:)` is a 'pure' function, the developer gains assurance from the tooling that it doesn't reference anything or cause any side effects.<br class=""><br class=""><br class="">```<br class="">class Recognizer {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>var nullabilityMemo: Bool?<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>var isNullable: Bool {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>pfunc _computeNullability(of recognizer: Recognizer) -&gt; Bool {…}<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>if let back = nullabilityMemo {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>return back<span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>} else {<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>let back = &nbsp;_computeNullability(of: self)<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>nullabilityMemo = back<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>return back<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>}<br class=""><span class="m_4197988501921103072Apple-tab-span" style="white-space:pre-wrap">        </span>}<br class="">}<br class="">```<br class=""><br class="">## Detailed design<br class=""><br class="">This proposal introduces a new annotation `=&gt;`, which is to be accepted everywhere `-&gt;` currently is. Members created using this kewyord must follow the rules listed in the introduction.<br class=""><br class="">## Impact on existing code<br class=""><br class="">This is an additive feature unless alternative 2 is chosen and, as such, should not require an effect on existing code. It could be used to annotate closures accepted by methods in the standard library such as `map`, `filter`, and `reduce`. While this would fit well with their typical use, such a change is not necessarily part of this proposal.<br class=""><br class="">## Alternatives considered<br class=""><br class="">It should be noted that neither of these alternatives can remain consistent for inline closures.<br class="">1. keyword `pfunc` (pronounciation: pifəŋk) for 'pure' functions. <br class="">2. `proc` keyword for 'impure' functions and 'func' for 'pure' functions. This would be a massively source breaking change and, as such, is unlikely to have any feasibility. It is, however, the most clean semantically, in my opinion.<br class=""><br class="">______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class=""></blockquote><br class="">______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class=""></div></div></blockquote></div></div></div><br class=""></div><br class="">______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
<br class=""></blockquote></div><br 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=""></div></body></html>