<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=""><div class="">I'm just going to point out to the documentation about pure functions in the D language which has an unusual but very practical take on enforcing purity. It's interesting, and it might also provide a list for things that might need be addressed in this proposal.</div><div class=""><a href="https://dlang.org/spec/function.html#pure-functions" class="">https://dlang.org/spec/function.html#pure-functions</a></div><br class=""><div><blockquote type="cite" class=""><div class="">Le 16 févr. 2017 à 12:03, T.J. Usiyan via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class=""># Pure Functions</div><div class=""><br class=""></div><div class="">* Proposal: [SE-NNNN](<a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md</a>)</div><div class="">* Author(s): [TJ Usiyan](<a href="https://github.com/griotspeak" class="">https://github.com/griotspeak</a>)</div><div class="">* Status: **Awaiting review**</div><div class="">* Review manager: TBD</div><div class=""><br class=""></div><div class="">## Introduction</div><div class=""><br class=""></div><div 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'.</div><div class=""><br class=""></div><div class="">'pure', in this context, means:</div><div class="">1. The function must have a return value</div><div class="">1. This function can only call other pure functions</div><div class="">1. This function cannot access/modify global or static variables.</div><div class=""><br class=""></div><div class="">## Motivation</div><div class=""><br class=""></div><div class="">Consider the following example where `_computeNullability(of:)` is meant to create its output solely based on the provided recognizer.</div><div class=""><br class=""></div><div class="">```</div><div class="">class Recognizer {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>var nullabilityMemo: Bool?</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>var isNullable: Bool {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>func _computeNullability(of recognizer: Recognizer) -&gt; Bool {…}</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>if let back = nullabilityMemo {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>return back<span class="gmail-Apple-tab-span" style="white-space:pre">                </span></div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>} else {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>let back = &nbsp;_computeNullability(of: self)</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>nullabilityMemo = back</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>return back</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>}</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>}</div><div class="">}</div><div class="">```</div><div 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`.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">## Proposed solution</div><div class=""><br class=""></div><div 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.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">```</div><div class="">class Recognizer {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>var nullabilityMemo: Bool?</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>var isNullable: Bool {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>pfunc _computeNullability(of recognizer: Recognizer) -&gt; Bool {…}</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>if let back = nullabilityMemo {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>return back<span class="gmail-Apple-tab-span" style="white-space:pre">                </span></div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>} else {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>let back = &nbsp;_computeNullability(of: self)</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>nullabilityMemo = back</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                        </span>return back</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>}</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>}</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">## Detailed design</div><div class=""><br class=""></div><div 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.</div><div class=""><br class=""></div><div class="">## Impact on existing code</div><div class=""><br class=""></div><div 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.</div><div class=""><br class=""></div><div class="">## Alternatives considered</div><div class=""><br class=""></div><div class="">It should be noted that neither of these alternatives can remain consistent for inline closures.</div><div class="">1. keyword `pfunc` (pronounciation: pifəŋk) for 'pure' functions.&nbsp;</div><div 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.</div><div class=""><br class=""></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=""><div class="">
<div style="color: rgb(0, 0, 0); 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; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); 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; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); 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; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; border-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; border-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; border-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">--&nbsp;<br class="">Michel Fortin</div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="text-align: -webkit-auto;" class=""><a href="https://michelf.ca" class="">https://michelf.ca</a></span></div></span></div></span></div></span></div></div></div></div>
</div>
<br class=""></body></html>