Question (/ TL; DR)
In the details below, we see that using the syntax of the style ( (unaryOperator)(operand), (binaryOperator)(lhsOperand, rhsOperand)) function to call operator functions seems to override the normal rules for resolving type overloads; an overload simply selects the first (in the order of definition) overload that it can find.
- This is mistake? Or is it some kind of peculiar, but expected behavior of the syntax call-operator-by-function-style (
(unaryOperator)(operand), (binaryOperator)(lhsOperand, rhsOperand))?
Background
I just read Matt Gallagher's excellent post about some current Swift type checking issues
One of the issues raised in the article is the problems that may arise from the fact that general overloads are not taken into account when resolving operator overloads, given that there are no general alternatives. Gallagher shows one such “question” with the following example
prefix operator %% {}
prefix func %%(_ x: Float) -> Float { return x }
prefix func %%<I: Integer>(_ x: I) -> I { return x }
let y = %%1
print(y.dynamicType)
Naturally, we see the same result if we switch places to the two definitions of the operator %%above, i.e.
prefix operator %% {}
prefix func %%<I: Integer>(_ x: I) -> I { return x }
prefix func %%(_ x: Float) -> Float { return x }
Note also that the aforementioned strictly non-general priority for overload resolution is missing for functions, as Gallagher shows with the following example
/* resolves x to "Int", no matter the order
of these two function definitions */
func f(_ x: Float) -> Float { return x }
func f<I: Integer>(_ x: I) -> I { return x }
let x = f(1)
print(x.dynamicType) // "Int"
Additional information related to the issue
Now about the features. We can name binary and unary operations in the style of the function using the syntax (binaryOperator)(lhsOperand, rhsOperand)and (unaryOperator)(operand), respectively. For instance.
let a = (+)(1, 2)
let b = (-)(a)
, %%, , , ( , ) y , -, , %%.
prefix operator %% {}
prefix func %%(_ x: Float) -> Float { return x }
prefix func %%<I: Integer>(_ x: I) -> I { return x }
let y = (%%)(1)
print(y.dynamicType)
prefix operator %% {}
prefix func %%<I: Integer>(_ x: I) -> I { return x }
prefix func %%(_ x: Float) -> Float { return x }
let y = (%%)(1)
print(y.dynamicType)
† , () %%1, (%%)(1) , , .
prefix operator %% {}
prefix func %%(_ x: Double) -> Double { return x }
prefix func %%<I: Integer>(_ x: I) -> I { return x }
prefix func %%(_ x: Float) -> Float { return x }
let y = (%%)(1)
print(y.dynamicType)
[†]: : , , , , , , . , - "" : , , .
( Swift 3.0 IBM Swift Sandbox, Swift 2.2, XCode 7.3, )