<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">So I was thinking the other day (and by "the other day" I mean "It just occurred to me") that Swift's custom operator declaration mechanism is pretty sweet (it's become even sweeter ever since numeric precedence values were replaced with purely relativistic precedence trees). There are currently only two problems with them that grind my operator-declaring endeavors to a painful halt:<div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>1. The fact that most punctuation characters on the keyboard (think - ASCII) are reserved, so any custom operator either has to be a long sequence of two or three non-reserved ASCII characters or have to include difficult-to-type unicode punctuation characters.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>2. The fact that anything that passes as an identifier character (which includes a surprisingly wide array of punctuation characters) is off the table as well.</div><div class=""><br class=""></div><div class="">I have no good idea how to deal with the first problem, but the second problem seems to have a bafflingly simple solution that I can't believe I haven't noticed until now.</div><div class="">And the reason to even try to solve that problem is because Swift already has a lot of operators with identifiers in them:</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* infix is</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* infix as</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* infix as?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* infix as!</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* prefix try</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* prefix try?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* prefix try!</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* prefix throw</div><div class="">So this is hardly a new concept to Schwifty developers.</div><div class=""><br class=""></div><div class="">The way I think could this could be solved is by introducing custom keywords that can be defined just like custom operators can be.</div><div class="">The custom keyword has to be a valid identifier and is defined much like a non-infix custom operator (by writing `keyword`, followed by an identifier).</div><div class=""><br class=""></div><div class="">Custom operator definitios would now be permitted to have any number of non-adjacent keywords among usual punctuation characters.</div><div class="">Any identifier that matches a custom keyword has to be escaped with backticks just like it's the case for regular keywords.</div><div class="">Prefix operators may not end with a keyword.</div><div class="">Postfix operators may not begin with a keyword.</div><div class="">Infix operators that either begin or end with a keyword may not be used without whitespaces.</div><div class=""><br class=""></div><div class="">Here's an example:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class=""><font color="#941751" class="">precedencegroup</font>&nbsp;AggregateFormingPrecedence {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">higherThan</font>: TernaryPrecedence</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">lowerThan</font>:&nbsp;</font><span style="font-family: Menlo;" class="">LogicalDisjunctionPrecedence</span></div><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><div class=""><font face="Menlo" class=""><font color="#941751" class="">precedencegroup</font>&nbsp;DimensionFormingPrecedence {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">higherThan</font>:&nbsp;</font><span style="font-family: Menlo;" class="">Aggregate</span><span style="font-family: Menlo;" class="">FormingPrecedence</span></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">lowerThan</font>: LogicalDisjunctionPrecedence</font></div><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><font color="#941751" class="">keyword</font> of</font></div><div class=""><font face="Menlo" class=""><font color="#941751" class="">keyword</font> by</font></div><div class=""><div class=""><font face="Menlo" class=""><font color="#941751" class="">infix</font>&nbsp;<font color="#941751" class="">operator</font>&nbsp;of:&nbsp;</font><span style="font-family: Menlo;" class="">Aggregate</span><span style="font-family: Menlo;" class="">FormingPrecedence</span></div></div><div class=""><font face="Menlo" class=""><font color="#941751" class="">infix</font> <font color="#941751" class="">operator</font> by: DimensionFormingPrecedence</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><div class=""><font face="Menlo" class=""><font color="#941751" class="">public</font> <font color="#941751" class="">struct</font> <font color="#008f00" class="">Matrix</font>&lt;<font color="#008f00" class="">Element</font>&gt; <font color="#941751" class="">where</font> <font color="#008f00" class="">Element</font>: <font color="#008f00" class="">FloatingPoint</font>&nbsp;{</font></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">public</font>&nbsp;<font color="#941751" class="">struct</font> <font color="#941751" class="">Dimensions</font> {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">let</font>&nbsp;rows: <font color="#008f00" class="">Int</font><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">let</font> columns: <font color="#008f00" class="">Int</font><br class=""></font><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</font></div><div class=""><font face="Menlo" class=""><br class=""></font><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#941751" class="">public</font>&nbsp;<font color="#941751" class="">init</font>(dimensions: <font color="#008f00" class="">Dimensions</font>, value: <font color="#008f00" class="">Element</font>) {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><font color="#941751" class="">self</font>.elements = .<font color="#941751" class="">init</font>(repeating: value, count: dimensions.rows * dimensions.columns)</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">private</font> <font color="#941751" class="">var</font> elements: [</font><span style="color: rgb(0, 143, 0); font-family: Menlo;" class="">Element</span><font face="Menlo" class="">]</font></div><div class=""><span class="Apple-tab-span" style="white-space:pre"><font face="Menlo" class="">        </font></span></div><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><font color="#941751" class="">public static func</font> by(_ rows: <font color="#008f00" class="">Int</font>, _ columns: <font color="#008f00" class="">Int</font>) -&gt; Matrix.Dimensions {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">return</font> .<font color="#941751" class="">init</font>(rows: rows, columns: columns)</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><font color="#941751" class="">public static func</font> of&lt;<font color="#008f00" class="">Element</font>&gt;(_ dimensions: Matrix.Dimensions, _ value: Element) -&gt; <font color="#008f00" class="">Matrix</font>&lt;<font color="#008f00" class="">Element</font>&gt;&nbsp;</font><font color="#941751" style="font-family: Menlo;" class="">where</font><span style="font-family: Menlo;" class="">&nbsp;</span><font color="#008f00" style="font-family: Menlo;" class="">Element</font><span style="font-family: Menlo;" class="">:&nbsp;</span><font color="#008f00" style="font-family: Menlo;" class="">FloatingPoint</font><span style="font-family: Menlo;" class="">&nbsp;{</span></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">return</font> .<font color="#941751" class="">init</font>(dimensions: dimensions, value: value)</font></div><div class=""><span style="font-family: Menlo;" class="">}</span></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><font color="#941751" class="">let</font> m =&nbsp;</font><span style="font-family: Menlo;" class="">3 by 4 of 1.0 <font color="#797979" class="">// m is of type Matrix&lt;Double&gt;</font></span></div><div class=""><br class=""></div><div class="">I feel like these kind of changes would be best considered in the early stages of a major release (namely, Swift 5) so that they have time to be refined and tested.</div><div class="">What do you guys think?</div><div class=""><br class=""></div></div></body></html>