this is a bit of a historic investigation i want to share with you. not a pitch, or anything, i do not expect any changes to swift language in that area. this is an observation of what had happened and what could have happened.
have a look at SE-0077 Improved operator declarations.
there were three motivations listed there:
1. Problems with numeric definition of precedence
2. Problems with a single precedence hierarchy
3. Problems with current operator declaration syntax
let me start from the last one: "Current operator declaration syntax is basically an unstructured bag of words”:
infix operator <> { precedence 100 associativity left }
i view this bullet point as an “add-on” to the main topic of that proposal, for example we could have addressed just that bit without changing anything else:
infix operator <> { precedence: 100, associativity: left }
so let’s forget (3) and move to the next one: (2)
it turns out that at the end of the day swift didn’t change that aspect of the operator precedence.. we still have a single precedence hierarchy for built-in operators (see the operator table in operator_declarations of the language definition or command click on the “import Swift” too see for yourself).
Looking at the usage in custom operators — (my tool for this recently is an advanced search on github) — the owerhelming majority of those custom operators do not create custom precedence group at all, referencding the existing one. and the overhelming majority of those that do, base their precedence (using higherThan) in relation to one of the system precedence groups, thus putting their precedence group firmly inside the single system hierarchy of precedences.
given that observation my assumption here (welcome for your feedback if you are on the contrary) is this: we won’t lose too much if (2) was not there.
having said that, let us forget (2) and switch to the “main” one (1):
the reasoning here is clear and understandable. but let's consider this alternative: “use floating point numbers for precedence”. one can put an infinite number of real numbers between two different real numbers and even if we regard the 32/64 bit IEEE limitations the amount of numbers we can put between, say, 0.001 and 0.002 is wast and well beyond our needs to express precedence levels.
as i can see in the proposal — this alternative was not considered (*). i saw similar trend in other proposals as well - typically the authors are so focused on their preferred solution that they are not seriously considering anything else. (hint for the future language designers: do something about it).
(*) using Int32/64 and selecting the min/max precedence to 0 ... Int.max along with adjusting the existing levels, e.g. not "90" but "90_000_000" is not listed as considered either, even Int32 would be well more than enough and if not - there is Int64.
should we considered and then accepted the idea of floating / int32/64 precedence we would have a different language today in that area, smth like that:
enum Precedence: Float {
minimal = 0.0
bitwiseShift = 90.0
multiplication = 100.0
addition = 110.0
rangeFormation = 120.0
casting = 130.0
nilCoalescing = 140.0
comparison = 150.0
logicalConjunction = 160.0
logicalDisjunction = 170.0
ternary = 180.0
assignment = 190.0
maximum = 1000.0
init(…) { … }
}
infix operator <> { precedence: .comparison, associativity: left }
// custom:
extension Precedece {
static let wtf = Precedence(123.456)
}
infix operator @$#% { precedence: .wtf, associativity: left }
as i said, this is not a pitch. rather a historic observation of current affairs and missed opportunities. presented by a grumpy fella :-)