See inline

> Am 03.04.2016 um 13:26 schrieb Ross O'Brien via swift-evolution 
> <[email protected]>:
> 
> 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?
> 

We could allow operator precedence overriding to resolve ambiguity. However 
this overriding should only be module internal since it would override the 
existing precedences in the other modules.

@AHTOH
Why do you use #keyword ?
I think defining a operator with

    infix operator + {
         associativity: left
    }

is perfectly fine since it is similar to class/struct/enum declaration.

    // and it's precedence
    precedence(+ lessThan *)

Note the missing "," and ":" before and after "lessThan" in order to give both 
operators the same importance (minor issue).

I feel that

    #precedence(+, lessThan: *)

puts too much importance on the first operator.

Best regards
- Maximilian

> 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 
>> <[email protected]> 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 
>>> <[email protected]> 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
>>> 
>>> Motivation
>>> 
>>> 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.
>>> 
>>> 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.
>>> 
>>> 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.
>>> 
>>> 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 }
>>> Proposed solution
>>> 
>>> 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.
>>> 
>>> 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  // ok
>>> 1 + 2 - 3  // error!
>>> #precedence(-, equalTo: +)
>>> 1 + 2 - 3  // now ok
>>> Precedence equality can only be defined for operators with same 
>>> associativity.
>>> 
>>> 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.
>>> 
>>> 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)
>>> 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.
>>> 
>>> Alternatives considered
>>> 
>>> 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
>>> [email protected]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to