Custom Operator Precedence Issue in Swift? - 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?

Related

My custom operator needs a precedence group?

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

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?

Unary operator '++'

I am interested and beginning in Swift, but I can't fix that :
func countvalue(tableau : [String]){
var b : Int = 0
for var b in tableau {
b++ // Unary operator '++' cannot be applied to an operand of type #lvalue String'
}
print("Il y a \(b) valeurs dans ce tableau.")
}
The b in your loop is a different variable than the one outside the loop, and is masking it. Since tableau is an array of Strings, b in the loop is a String, and thus cannot be incremented.
I think what you want is this...
func countvalue(tableau : [String]){
var b : Int = 0
for _ in tableau {
// the values in the array are not used so just ignore them with _
b++ // Unary operator '++' cannot be applied to an operand of type #lvalue String'
}
print("Il y a \(b) valeurs dans ce tableau.")
}
But the value of b will be the same if you do...
var b = tableau.count
Except this is a lot more efficient as it does not have to iterate every value of the array.