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
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?
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?
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.
In the various Lisps, it's possible for me to create a sequence of functions as if they'd just been normal values:
(def ops [+ - * /])
Which I can then iterate through, again, as if they were just normal values:
(doseq [op ops] // (doseq (op ops) is like for (op <- ops) in scala
(println (op 1 2 3 4)))
Now, I've tried a few things in Scala, all of them failing:
scala> List(+, -, *, /)
<console>:1: error: illegal start of simple expression
List(+, -, *, /)
^
scala> List[Double => Double](+, -, *, /)
<console>:1: error: illegal start of simple expression
List[Double => Double](+, -, *, /)
^
scala> List[Double => Double](+_, -_, *_, /_)
<console>:8: error: not found: value *
List[Double => Double](+_, -_, *_, /_)
^
<console>:8: error: not found: value /
List[Double => Double](+_, -_, *_, /_)
^
So what's the correct procedure of defining a list of functions/operators in Scala?
The problem is that these functions are binary operators, i.e., they take two operands and return one. So you have to use:
List[(Double, Double) => Double](_ + _, _ - _, _ * _, _ / _)
In Scala, most value-level operators are actually unary instance methods (maybe all are, not sure if there are counterexmaples). So when you talk about, say, addition of two values of type Double, you're really referring to a method of the first value that takes the second value as a parameter. The familiar infix operator syntax is just sugar. In other words,
scala> 5.7 + 6.3
res0: Double = 12.0
is really just a nice shorthand for:
scala> 5.7.+(6.3)
res1: Double = 12.0
As #bluenote10 already mentioned, you can capture these operators by creating anonymous function that take both the first instance and its operand as parameters and returns the result of the + method:
scala> (lhs: Double, rhs: Double) => lhs + rhs
res2: (Double, Double) => Double = <function2>
Or as in #bluenote10's example, if the type can be inferred (like in a list with the type provided), you can use the nice underscore syntax:
scala> val doublePlus: (Double, Double) => Double = _ + _
doublePlus: (Double, Double) => Double = <function2>