<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br></div><div><br>On 17 Feb 2017, at 23:30, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 17, 2017, at 4:17 PM, Daniel Leping &lt;<a href="mailto:daniel@crossroadlabs.xyz" class="">daniel@crossroadlabs.xyz</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">I don't think I can (fully) agree with you, because a closure purity is not something you "define". It's rather what you use inside. Though I totally understand your concern and a wish to have localized errors.</div><div class=""><br class=""></div><div class="">However, I think it's totally consistent if you use a full form in a way:</div><div class=""><br class=""></div><div class="">{ (a) =&gt; B in</div><div class="">return a.toB()</div><div class="">}</div><div class=""><br class=""></div><div class="">What I mean is that short form can auto determine. If you want to be explicit... use the long form.</div><div class=""><br class=""></div><div class="">Would this work for you, @Matthew?</div></div></blockquote><div><br class=""></div><div>What I am saying is that I don’t think I should have to use the entire long form just to specify it’s a pure closure. &nbsp;Something like the following would be acceptable:</div><div><br class=""></div><div>{= $0.some.pure.expression() }</div><div>or</div>{=&gt; $0.some.pure.expression() }</div></div></blockquote><div><br></div><div>Or:</div><div>{ x =&gt; x.some.pure.expression() }</div><br><blockquote type="cite"><div><div>But I don’t want to be required to write out a name for the arguments and a return type for single expression closures like this.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><div class="gmail_quote"><div class="">On Sat, 18 Feb 2017 at 0:09 Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>&gt; wrote:<br class=""></div><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="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Feb 17, 2017, at 4:05 PM, Daniel Leping &lt;<a href="mailto:daniel@crossroadlabs.xyz" class="gmail_msg" target="_blank">daniel@crossroadlabs.xyz</a>&gt; wrote:</div><br class="m_2345984177384601287Apple-interchange-newline gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I personally like a lot =&gt; syntax for several reasons:<br class="gmail_msg"></div><div class="gmail_msg">1. Consistent</div><div class="gmail_msg">2. Enforced return type</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">As for the closures, I don't think we need an indication here. If it calls any impure function or captures a variable from outside - it's impure by definition. The compiler should decide if a closure can be treated pure. Same as with throwing.</div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">I’m not sure about this.&nbsp; I would like the ability to syntactically state the intent that a closure is pure, and ideally do so in a way that doesn’t lose the conciseness of the closure (i.e. we shouldn’t have to give up any of the syntactic sugar available for simple closures).&nbsp; A big benefit of allowing us to state intent like this is that it localizes error messages.</div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">As for the situation with currying (and other compositions), the situation is a lot more complicated than with rethrows. However, it's still deductible in compile time with the same mechanism as described above for closures.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I tend to agree we could use ~&gt; (looks good to me... volatile :)) for the function type definitions as an "unknown purity". The return type purity dependence graph can be built automatically at compile time. With this graph compiler can determine the returned function purity in every place function is used.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The use of ~&gt; should of course be limited to argument and return types of pure functions only. I think there might be a possibility of use in typealias, but need to think more about it.</div><div class="gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg">On Fri, 17 Feb 2017 at 22:59 Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="gmail_msg m_2345984177384601287m_752351108347702395Apple-interchange-newline"><div class="gmail_msg"><div style="word-wrap:break-word" class="gmail_msg">Out of curiosity, what are the benefits to being able to define that a closure must be pure as a parameter/type definition, as opposed to defining a particular closure to being pure while being passed?&nbsp; What guarantees does it give you as the caller of the closure?</div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">If you only accept pure closures and otherwise meet the criteria of a pure function then you are pure.&nbsp; If you have a function like that and want to accept both pure and impure closures and receive the purity of the closure provided then we need syntax indicating something similar to `rethrows`, but for purity.</div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Thanks,</div><div class="gmail_msg">Jon</div><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Feb 16, 2017, at 1:18 PM, T.J. Usiyan &lt;<a href="mailto:griotspeak@gmail.com" class="gmail_msg" target="_blank">griotspeak@gmail.com</a>&gt; wrote:</div><br class="gmail_msg m_2345984177384601287m_752351108347702395Apple-interchange-newline"><div class="gmail_msg"><div class="gmail_msg">I am ok with a keyword but&nbsp;`pure` in front of func doesn't work well with inline closures.<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">A few people talked through many of these issues starting with this tweet. <a href="https://twitter.com/griotspeak/status/832247545325842432" class="gmail_msg" target="_blank">https://twitter.com/griotspeak/status/832247545325842432</a></div></div><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull <span class="gmail_msg">&lt;<a href="mailto:jhull@gbis.com" class="gmail_msg" target="_blank">jhull@gbis.com</a>&gt;</span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg">+1 for the idea of pure functions in swift.&nbsp; Seems like it would enable a lot of good optimizations (in some cases even just evaluating the function at compile time).<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">-1 on the specific notation.&nbsp; I would much rather just put the word ‘pure’ in front of ‘func’, the same way we put ‘mutating' in front of mutating functions… it seems to me like these are part of the same family.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I agree we should allow inout.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Thanks,</div><div class="gmail_msg">Jon</div><div class="gmail_msg"><br class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div class="m_2345984177384601287m_752351108347702395h5 gmail_msg"><div class="gmail_msg">On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801Apple-interchange-newline"></div></div><div class="gmail_msg"><div class="gmail_msg"><div class="m_2345984177384601287m_752351108347702395h5 gmail_msg"><div class="gmail_msg"><div class="gmail_msg"># Pure Functions</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">* Proposal: [SE-NNNN](<a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md" class="gmail_msg" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md</a>)</div><div class="gmail_msg">* Author(s): [TJ Usiyan](<a href="https://github.com/griotspeak" class="gmail_msg" target="_blank">https://github.com/griotspeak</a>)</div><div class="gmail_msg">* Status: **Awaiting review**</div><div class="gmail_msg">* Review manager: TBD</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">## Introduction</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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'.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">'pure', in this context, means:</div><div class="gmail_msg">1. The function must have a return value</div><div class="gmail_msg">1. This function can only call other pure functions</div><div class="gmail_msg">1. This function cannot access/modify global or static variables.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">## Motivation</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Consider the following example where `_computeNullability(of:)` is meant to create its output solely based on the provided recognizer.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">```</div><div class="gmail_msg">class Recognizer {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>var nullabilityMemo: Bool?</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>var isNullable: Bool {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>func _computeNullability(of recognizer: Recognizer) -&gt; Bool {…}</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>if let back = nullabilityMemo {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>return back<span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span></div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>} else {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>let back = &nbsp;_computeNullability(of: self)</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>nullabilityMemo = back</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>return back</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>}</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div class="gmail_msg">}</div><div class="gmail_msg">```</div><div class="gmail_msg">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`.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">## Proposed solution</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">```</div><div class="gmail_msg">class Recognizer {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>var nullabilityMemo: Bool?</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>var isNullable: Bool {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>pfunc _computeNullability(of recognizer: Recognizer) -&gt; Bool {…}</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>if let back = nullabilityMemo {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>return back<span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span></div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>} else {</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>let back = &nbsp;_computeNullability(of: self)</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>nullabilityMemo = back</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                        </span>return back</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>}</div><div class="gmail_msg"><span class="gmail_msg m_2345984177384601287m_752351108347702395m_-8285033497674018801gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div class="gmail_msg">}</div><div class="gmail_msg">```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">## Detailed design</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">## Impact on existing code</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">## Alternatives considered</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">It should be noted that neither of these alternatives can remain consistent for inline closures.</div><div class="gmail_msg">1. keyword `pfunc` (pronounciation: pifəŋk) for 'pure' functions.&nbsp;</div><div class="gmail_msg">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.</div><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div><span class="gmail_msg">
_______________________________________________<br class="gmail_msg">swift-evolution mailing list<br class="gmail_msg"><a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg"></span></div></blockquote></div><br class="gmail_msg"></div></div></blockquote></div><br class="gmail_msg"></div>
</div></blockquote></div><br class="gmail_msg"></div></div></div>_______________________________________________<br class="gmail_msg">swift-evolution mailing list<br class="gmail_msg"><a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg"></div></blockquote></div></div>_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div></div>
</div></blockquote></div></div></blockquote></div></div>
</div></blockquote></div><br class=""></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>