[swift-evolution] [Proposal] Custom operators

James Campbell james at supmenow.com
Sun Apr 3 06:38:15 CDT 2016


In these case of module operator conflicts perhaps there could be a way we
could import these operators ?

Likes a #importOperators(OtherModule) or some kind of build flag.

*___________________________________*

*James⎥Future Prime Minister*

*james at supmenow.com <james at supmenow.com>⎥supmenow.com <http://supmenow.com>*

*Sup*

*Runway East *

*10 Finsbury Square*

*London*

* EC2A 1AF *

On Sun, Apr 3, 2016 at 12:26 PM, Ross O'Brien via swift-evolution <
swift-evolution at swift.org> wrote:

> There is a problem here of duplicated operators or custom precedence, and
> how that gets passed between modules.
> Assume there are three modules, A, B and C. B defines a custom operator
> **. A and C each define a custom operator ++, and their meanings are
> different (though, even if their meanings were the same, I'm not sure if
> they could unify).
>
> Module D uses A and B as dependencies and sets a custom precedence on ++
> and **. Module E uses B and C and has a different precedence on ++ and **.
> You're working on Module F which uses D and E. Which ++ and which
> precedence does F get implicitly?
>
> I'm wondering whether we can treat operators the way we recently decided
> to treat selectors: if there is an ambiguity, it should be possible not
> just to specify which module they came from, but their fixity or argument
> types. If module D decides that '++' should refer to 'traditional postfix
> number incrementation', and F decides that it should be an infix 'conjoin
> two numbers as a string and turn the result into a number (e.g. 5 ++ 4 ->
> 54)' then a #selector-like operator signature would come in really handy.
>
>
> On Sun, Apr 3, 2016 at 12:10 PM, Taras Zakharko via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> I think this is a great suggestion! One potential problem I can see (if I
>> understood this correctly) is that modules are allowed to set up their own
>> precedence rules for operators defined elsewhere. I think this might lead
>> to some difficult to debug errors if a developer of one module (who is used
>> to certain conventions) then has to work with a different, independent
>> module (where the conventions are different). This is one area where
>> numerical precedence weights seem to be superior as they at least refer to
>> a common subjective coordinate system.
>>
>> Maybe one should also have visibility for precedence, for instance having
>> precedence module-internal by default?
>>
>> Best,
>>
>>  — Taras
>>
>> On 03 Apr 2016, at 11:36, Антон Жилин via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>> Swift 2.2 is out, and I restart discussion on syntax for custom
>> operators. I insist that this time we should focus less on linguistic
>> aspects.
>>
>>
>> https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md
>>
>> Introduction
>>
>> Replace syntax of operator definition:
>>
>> infix operator <> { precedence 100 associativity left }
>>
>> With a directive:
>>
>> #operator(<>, fixity: infix, associativity: left)
>>
>> Also replace numeric definition of precedence with separate comparative
>> precedence definitions:
>>
>> #precedence(+, lessThan: *)
>> #precedence(+, equalTo: -)
>>
>> Swift-evolution thread: link to the discussion thread for that proposal
>> <https://lists.swift.org/pipermail/swift-evolution>
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation>
>> Motivation
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence>Problems
>> with numeric definition of precedence
>>
>> In the beginning, operators had nice precedence values: 90, 100, 110,
>> 120, 130, 140, 150, 160.
>>
>> As time went, new and new operators were introduced. Precedence could not
>> be simply changed, as this would be a breaking change. Ranges got
>> precedence 135, as got precedence 132. ?? had precedence greater than <,
>> but less thanas, so it had to be given precedence 131.
>>
>> Now it is not possible to insert any custom operator between < and ??.
>> It is an inevitable consequence of current design: it will be impossible to
>> insert an operator between two existing ones at some point.
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy>Problems
>> with a single precedence hierarchy
>>
>> Currently, if an operator wants to define precedence by comparison to one
>> operator, it must do so for all other operators.
>>
>> In many cases, this is not wished. Example: a & b < c is a common error
>> pattern. a / b as Double is another one. C++ compilers sometimes emit
>> warnings on these. Swift does not.
>>
>> The root of the problem is that precedence is defined between all
>> operators. If & had precedence defined only by comparison to other
>> bitwise operators and / – only to arithmetic operators, we would have to
>> place parentheses in such places, not get subtle bugs, and not ever have to
>> look at the huge operator precedence table.
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax>Problems
>> with current operator definition syntax
>>
>> Some argue that current operator syntax is not consistent with other
>> language constructs. Properties of operators have dictionary semantics and
>> should be defined as such. It is a rather weak argument right now, but
>> after reworking of precedence, the new syntax will be more to place. More
>> reasons are given below.
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions>Conflicts
>> of operator definitions
>>
>> Consider two operator definitions in different modules.
>>
>> Module A:
>>
>> infix operator |> { precedence 137 associativity left }
>>
>> Module B:
>>
>> infix operator |> { precedence 138 associativity left }
>>
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution>Proposed
>> solution
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition>Change
>> syntax for operator definition
>>
>> #operator(<>, fixity: infix, associativity: left)
>> #operator(!, fixity: postfix)
>>
>> First parameter of #operator directive is name of the operator. Then
>> goes required parameter fixity that can be infix,prefix, or postfix.
>> Then, for infix operators, goes optional associativity parameter that
>> can be left or right.
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence>Comparative
>> precedence
>>
>> Remove precedence property from operator definitions. Instead, introduce
>> #precedence directive:
>>
>> #precedence(+, lessThan: *)
>> #precedence(*, equalTo: /)
>>
>> Omission of parentheses is allowed only when precedence between the two
>> operators is defined.
>>
>> 1 + 2 * 3  // ok1 + 2 - 3  // error!
>> #precedence(-, equalTo: +)1 + 2 - 3  // now ok
>>
>> Precedence equality can only be defined for operators with same
>> associativity.
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution>Conflict
>> resolution
>>
>> Precedence rules can be added freely across modules. Ability to omit
>> parentheses around more operators will not break any code in included
>> modules. On the other hand, conflicting precedence rules result in an error:
>>
>> #precedence(*, lessThan: +)  // error, previously defined `+` < `*`
>>
>> Operator definitions do nut cause conflicts, unless they are infix and
>> one of them has associativity: left, but another one has associativity:
>> right.
>>
>> #operator(!, fixity: prefix)  // ok, duplicated definitions
>> #operator(<>, fixity: infix)
>> #operator(<>, fixity: infix, associativity: left)  // ok, now left associative
>> #operator(+, fixity: infix, associativity: right)  // error: associativity conflict
>>
>> So, if two modules define a custom operator with somewhat similar
>> semantics (at least associativity), they can be used together. Prefix and
>> postfix operators can never have conflicts in definitions. If they define
>> different precedence by comparison to same operators, then, most probably,
>> they had completely different semantics, and the situation is similar to
>> conflict of functions.
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design>Detailed
>> design
>>
>> operator keyword and local keywords associativity, precedence, left,
>> right will be removed.
>>
>> Directives with following (informal) syntax will be added:
>>
>> #operator(OPERATOR_NAME, fixity: FIXITY)
>> #operator(OPERATOR_NAME, fixity: infix, associativity: ASSOCIATIVITY)
>> #precedence(OPERATOR_NAME, lessThan: OPERATOR_NAME)
>> #precedence(OPERATOR_NAME, equalTo: OPERATOR_NAME)
>>
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code>Impact
>> on existing code
>>
>> Standard library operator declarations will need to be rewritten. Some of
>> the existing precedence rules will need to be rewritten using #precedence
>>  directive.
>>
>> More importantly, it needs to be discussed what operator precedence rules
>> do *not* need to be retained.
>>
>> User defined operators will need to be rewritten as well. But precedence
>> will have to be defined by the user. Meanwhile, we can automatically insert
>> parentheses to user code where needed.
>>
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered>Alternatives
>> considered
>> <https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence>Leave
>> current operator syntax (but change precedence)
>>
>> #precedence does not make sense to be defined inside of operator
>> definition, as it describes relationship of two operators. If so, then we
>> are left with the following declaration syntax:
>>
>> prefix operator ! { }infix operator |> { }infix operator <> { associativity left }
>>
>> If body of operator can only contain associativity (in some cases), then
>> the existence of body itself makes no sense.
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160403/ac82c863/attachment.html>


More information about the swift-evolution mailing list