My custom operator needs a precedence group? - swift

So I have a custom operator ≈ that works fine when comparing one pair of numbers but fails when I try to compare more than one pair. The code snippet below can be thrown right into a playground to replicate the error.
infix operator ≈
func ≈ (lhs: Int, rhs: Int) -> Bool {
lhs < rhs + 80 && lhs > rhs - 80
}
let results = 100 ≈ 75 && 89 ≈ 78 //<-- `Adjacent operators are in unordered precedence groups 'DefaultPrecedence' and 'LogicalConjunctionPrecedence'`
I read the docs on it but did not receive much understanding on how to fix this error.

You either need to group your operands:
let results = (100 ≈ 75) && (89 ≈ 78)
Or define your new operator precedence:
precedencegroup CongruentPrecedence {
lowerThan: MultiplicationPrecedence
higherThan: AdditionPrecedence
associativity: left
}
infix operator ≈:CongruentPrecedence

Related

Custom Operator Precedence Issue in Swift?

I'm trying to implement a custom infix power operator using the "^" character with the following code, but I'm getting unexpected results.
precedencegroup PowerPrecedence {
associativity: right
lowerThan: BitwiseShiftPrecedence
higherThan: MultiplicationPrecedence
}
infix operator ^ : PowerPrecedence
func^(lhs:Float,rhs:Float) -> Float {
return pow(lhs,rhs)
}
When I use the ^ operator in the following statement,
let x = 1 + 10 ^ Float(2)
I expect x to be 1 + (10^2) = 101, but x is (1+10)^2 = 121 instead. What am I missing?

Why has !== lower precedence than === in Scala?

Following code does not compile:
implicit class TripleEq(val x: Int) {
def === (y: Int) = x == y
def !== (y: Int) = x != y
}
val a = 0
val b = 1
if (a == a && b === b) {
println("Equal")
}
if (a != b && a !== b) {
println("Not equal")
}
The error is:
type mismatch;
found : Int
required: Boolean
The error goes away when I enclose the a !== b in parentheses.
I thought that operator precedence is defined by its first letter (see Tour of Scala) and therefore the precedence of !== should be the same as of ===, != or ==.
Why are parentheses required in the code above?
The answer is in the language specification of Assignment Operators:
There's one exception to this rule, which concerns assignment operators. The precedence of an assignment operator is the same as the one of simple assignment (=). That is, it is lower than the precedence of any other operator.
6.12.14 Assignment Operators
An assignment operator is an operator symbol (syntax category op in Identifiers) that ends in an equals character “=”, with the exception of operators for which one of the following conditions holds:
the operator also starts with an equals character, or
the operator is one of (<=), (>=), (!=).
Based on these rules !== is considered to be an assignment operator, while === is not.

Why is infix operator in swift not working?

My infix operator for powering isn't working. It adds or subtracts.
precedencegroup SquareSumOperatorPrecedence {
lowerThan: MultiplicationPrecedence
higherThan: AdditionPrecedence
associativity: left
assignment: false
}
infix operator ^: SquareSumOperatorPrecedence
func ^(lhs: Double, rhs: Double) -> Double {
return pow(lhs, rhs)
}
9 ^ 2// equals 81
// It gives me 11
I thought 9 ^ 2 would give me 81, but it gave me 11
^ is already defined as “bitwise XOR” operator for integer operands, and that is what 9 ^ 2 computes:
9 ^ 2 = 0b1001 ^ 0b0010 = 0b1011 = 11
(See Advanced Operators for more information about bitwise operators.)
You defined an operator for double operands, and that works as expected if you actually call it with Double values:
print(9.0 ^ 2.0) // 81

What is the purpose of allowing infix operators to have no an associativity?

Question 1: What is the purpose of allowing infix operators to have no associativity? (Possibly someone can give an example of a custom operator where this is preferable over actually including some associativity?)
Question 2: Is it possible to set a default associativity for infix operators, used for operators that have none?
We can define a custom infix operator without entering any associativity for it, e.g.
/* no associativity */
infix operator +| {
precedence 140
}
/* left associativity */
infix operator *| {
associativity left
precedence 140
}
Now, one could assume that using an infix operator without associativity (+| above) next to one with associativity (*| above)---where both operators have same precedence---would behave the same way as if both operators had the same associativity. However, this is not the case
func +| (lhs: Int, rhs: Int) -> Int {
return lhs+rhs
}
func *| (lhs: Int, rhs: Int) -> Int {
return lhs*rhs
}
let a : Int = 1 +| 2 *| 3
/* Error: non-associative operator is adjacent to
operator of same precedence */
If we add associativity left to the definition of +| above, the code runs fine (as expected)
/* no associativity */
infix operator +| {
associativity left
precedence 140
}
// ...
let a : Int = 1 +| 2 *| 3
/* 9, OK ((1+2)*3 = 9) */
If I have a look at the native Swift operators (Cmd-click Swift in import Swift), I can't find a single infix operators that is without associativity.
Why are we allowed to define infix operators without associativity, is there a possible use for such operators? Is it possible to set a default associativity for infix operators, such that operators with associativity will behave as if having the default associativity?

&& and || in Scala

since normal operators like +, ::, -> and so on are all methods which can be overloaded and stuff I was wondering if || and && are methods as well. This could theoretically work if this were methods in of the boolean object.
But if they are, why is something like
if (foo == bar && buz == fol)
possible? If the compiler reads from right to left this would invoke && on bar instead of (foo == bar)
6.12.3 Infix Operations An infix operator can be an arbitrary
identifier. Infix operators have
precedence and associativity defined
as follows:
The precedence of an infix
operator is determined by the
operator’s first character. Characters
are listed below in increasing order
of precedence, with characters on the
same line having the same precedence.
(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)
That is, operators starting with a
letter have lowest precedence,
followed by operators starting with
‘|’, etc.
There’s one exception to
this rule, which concerns assignment
operators(§6.12.4). The precedence of
an assigment operator is the same as
the one of simple assignment (=). That
is, it is lower than the precedence of
any other operator.
It follows with an explanation of associativity, and how it all combines in a expression with multiple operators. The Scala Reference makes good reading.
Because method starts with = has a higher precedence than method starts with &.
So (foo == bar && buz == fol) will become something like the following:
val tmp1: Boolean = (foo == bar)
val tmp2: Boolean = (buz == fol)
tmp1 && tmp2
Those two are definitely methods in scala.