I'm reading through the Swift 2.2 man and trying to understand a function in the mutating fun section here is the code
struct TestPoint {
var x = 0.0, y = 0.0
mutating func moveByX(deltaX: Double, y deltaY: Double) {
self = TestPoint(x: x + deltaX, y: y + deltaY)
}
}
var somePoint = TestPoint(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
The part I'm having trouble is with the func moveByX syntax. y deltaY for example how is this allowed? y is the declared variable in the struct but where does the deltaY bit come in ?
Only two values are passed in somePoint.moveBy
Is the value passed to both y and deltaY ?
thanks for any help
Internal and external parameter names
Let's look at the function signature of moveByX(...):
mutating func moveByX(deltaX: Double, y deltaY: Double)
/* | / ^^^^^^- internal name
| external name
internal name */
In Swift 2.2, by default the first function parameter as no external name (_), which means that the function moveByX(...) is called as:
someTestPointInstance.moveByX(someXvalue, y: someYvalue)
/* | \
no external name external name */
This means that the y that you see in the signature of moveByX(...) is just an external parameter name, one that no longer has any use when we've entered the body of the function (where the internal parameter name, deltaY is used). So the second argument passed to moveByX(...), to the external parameter name y, will be referred (in this case, copied to) deltaY in the actual function body.
Finally note that the x and y properties used in the body of the function
self = TestPoint(x: x + deltaX, y: y + deltaY)
are the member properties x and y as defined in the definition of the SomePoint struct.
Is the above still valid for Swift 3.0?
As somewhat covered above: if we don't supply explicit external parameter names for function parameters in Swift 2.2, then the following rules apply:
By default, the first function parameter will have no external parameter name (as seen above, _).
By default, all the following function parameters (second, third, and so on) will have the same external parameter name as internal parameter name. So in case we would've written the function signature of moveByX(...) as
mutating func moveByX(deltaX: Double, deltaY: Double)
then the external parameter name of the second parameter would've been deltaY, and we would've called the function as
someTestPointInstance.moveByX(someXvalue, deltaY: someYvalue)
In Swift 3.0 all parameter names follows the second rule above, namely; if no external parameter name has been supplied, then the internal parameter name will be used as external parameter name for all parameters.
That means the example above would have to be modified into something along the lines
struct TestPoint {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self = TestPoint(x: x + deltaX, y: y + deltaY)
}
}
// called as
someTestPointInstance.moveBy(x: someXvalue, y: someYvalue)
Read the chapter "Function Parameter Names".
Basically, in moveByX, "y" is an external parameter name for "deltaY" and it's used to label "deltaY".
Related
I was reading the apple doc when I fell upon this piece of syntax :
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// Prints "The point is now at (3.0, 4.0)"
Could someone explain why moveBy(x deltaX: Double, y deltaY: Double) has double labels on the arguments ?
Short answer: first argument label is for external caller, second one for local in-method use.
func moveBy(x deltaX: Double, y deltaY: Double) when calling looks following: moveBy(x: 1, y: 1), but inside the method deltaX and deltaY labels are used.
This naming style is not necessary, you can declare the method func moveBy(x: Double, y: Double) so x and y will be used inside the method.
To support legacy style, so from caller scope your method looks like moveBy(1, 1), you should place _ as first argument label: func moveBy(_ deltaX: Double, _ deltaY: Double). Such declarations are used in CocoaTouch to support legacy obj-c interface (ex. func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool).
The first label is Argument Labels and the second label is Parameter Names.
From Apple Document:
Each function parameter has both an argument label and a parameter
name. The argument label is used when calling the function; each
argument is written in the function call with its argument label
before it. The parameter name is used in the implementation of the
function. By default, parameters use their parameter name as their
argument label.
Usage:
func foo(with hoge: Int) {
return hoge * 2
}
let A = foo(with: 2) // A = 4;
Look closely to the Apple documentation.It is connected with Parameter Names.
You can override the default behavior for argument labels with one of
the following forms:
argument label parameter name: parameter type
_ parameter name: parameter type
Question (/TL;DR)
In the details below we see that using function style ((unaryOperator)(operand), (binaryOperator)(lhsOperand, rhsOperand)) syntax to call operator functions seemingly override the type checker's normal overload resolution rules; the the overload simply picks the first (in order of definition) overload that it can find.
Is this a bug? Or is this some peculiar but expected behaviour of the call-operator-by-function-style ((unaryOperator)(operand), (binaryOperator)(lhsOperand, rhsOperand)) syntax?
Background
I just read Matt Gallagher's excellent post on some current issues with the Swift type checker
Exponential time complexity in the Swift type checker
One of the issues raised in the article is the problems that can follow from the fact that generic overloads are not considered in the overload resolution of operators, given that non-generic alternatives exist. Gallagher shows one such "issue" with the following example
/* note: Swift 3 */
prefix operator %% {}
prefix func %%(_ x: Float) -> Float { return x }
prefix func %%<I: Integer>(_ x: I) -> I { return x }
let y = %%1 // integer literal
print(y.dynamicType) // "Float"
We naturally see the same result if we switch places on the two %% operator definitions above, i.e.
/* ... same result as above */
prefix operator %% {}
prefix func %%<I: Integer>(_ x: I) -> I { return x }
prefix func %%(_ x: Float) -> Float { return x }
Note also that the above strictly non-generic precedence for overload resolution is not present for functions, as shown by Gallagher 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"
Further details pertaining the question
Now on to the peculiarity. We may call binary and unary operations in function style using the (binaryOperator)(lhsOperand, rhsOperand) and (unaryOperator)(operand) syntax, respectively. E.g.
let a = (+)(1, 2) // 3
let b = (-)(a) // -3
Now, if we apply this syntax to the %% operator example above, the overload resolution rules as described above seems to no longer apply (no matter if we were to regard this as a function call or an operator call), as the type of y in the example above seemingly depends solely on the order in which the %% definitions appear.
prefix operator %% {}
prefix func %%(_ x: Float) -> Float { return x }
prefix func %%<I: Integer>(_ x: I) -> I { return x }
let y = (%%)(1)
print(y.dynamicType) // "Float"
/* swap the order of the definitions ... */
prefix operator %% {}
prefix func %%<I: Integer>(_ x: I) -> I { return x }
prefix func %%(_ x: Float) -> Float { return x }
let y = (%%)(1)
print(y.dynamicType) // "Int"
We may even, for some special conditions†, introduce additional overloads that (expectedly) yields ambiguity for the normal %%1 case, where the function style (%%)(1) case compiles without ambiguity, picking the first definition it can find.
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 }
// picks first %% definition it can find
let y = (%%)(1)
print(y.dynamicType) // "Double"
// ambiguity error as expected
//let z = %%(1) // error: ambiguous use of operator '%%'
[†]: The non-error behaviour of this last example is really unreliable: if we e.g. introduce a 2nd generic overload, the snippet runs only without error if a non-generic overload is defined first, but moreover only if a generic overload definition follows that non-generic one. I wont dwell further, however, into that special-case madness, but it seems like some "peek" behaviour: accepting a first defined non-generic overload given that a peek of the next definition shows a generic one.
(Tested for Swift 3.0 in the IBM Swift Sandbox. Swift 2.2 adapted version tested in XCode 7.3 playground as well as in a project)
What is the difference between these two Swift functions. I don't quite understand it. I know they are two different functions but they have different parameter structures.
func addTwoIntegers(first x:Int, second y:Int) -> Int{
return x + y
}
func multiplyTwoIntegers(x:Int, y:Int) -> Int{
return x * y
}
The difference between the two functions are evident if you use them inside of Swift’s playground. The first function uses external naming parameters which allow you to see the name of the parameters in kind of an Objective-c style fashion. For example, when I call addTwoIntegers, I will be able to call it like this while passing in the arguments addTwoIntegers(first: x, second: y). The second function does not use external naming parameters so you can only call it passing in the arguments such as multiplyTwoIntegers(2,2)
Copy this code into Xcode’s playground.
func addTwoIntegers(first x:Int, second y:Int) -> Int{
return x + y
}
func multiplyTwoIntegers(x:Int, y:Int) -> Int{
return x * y
}
var x = addTwoIntegers(first: 10, second: 10)
var y = multiplyTwoIntegers(2, 2)
println(x)
println(y)
The first uses externally named parameters as well as local parameter names and the second uses just locally name parameters
In Swift, if you have two variables :
var a:Int = 2
var b:Double = 3.4
And if you try to do :
var c = a+b
It will trigger an compile-time error, because you cannot add two variables that aren't of the same type.
But still, you could do :
var c = b+2
It would work because 2, by itself, doesn't have any type, so even if it isn't a decimal number (I mean, I din't wrote 2.0), it stills work.
Now, here is my question, why doesn't the same principle applies when I do :
acos(1)
But it works when I do :
acos(1.0)
I see that acos() can take Double, Float, and CGFloat as an argument, but shouldn't Xcode infer that 1 is in fact a Double ?
This is an interesting question. Note that if I define my own function myAcos that takes a Double, I can call it with myAcos(1):
func myAcos(d: Double) -> Double {
return 0.0
}
let a = myAcos(1) // This works
Now, if I add a second myAcos that takes and returns a Float:
func myAcos(f: Float) -> Float {
return 0.0
}
The call to myAcos(1) now give the error: error: ambiguous use of 'myAcos'
Then, I add a third function myAcos that takes and returns a CGFloat:
func myAcos(c: CGFloat) -> CGFloat {
return 0.0
}
The call to myAcos(1) then gives the error: error: could not find an overload for 'myAcos' that accepts the supplied arguments
If I then add a fourth myAcos function that takes and returns an Int, then myAcos(1) works:
func myAcos(i: Int) -> Int {
return 0
}
myAcos(1) // This works, again
So, the answer to your question appears to be that you can't call acos(1) because Swift can't figure out which version of acos you are attempting to call.
The language spec defines (see Literals in Language Reference) that 1 is an Integer literal and Swift doesn't allow implicit type conversion.
This is for good reasons because it makes expressions like
3 / 2
more unambiguous.
Example:
mutating func moveByX(deltaX: Double, y deltaY: Double)
The first parameter takes a Double and saves it in that method scope as deltaX. However, what are y and deltaY?
I read this and can't find anything about it: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
This is how Swift mimics Objective C's named parameters (pseudo naming of arguments). Its pretty easy to break down.
mutating func moveByX(deltaX: Double, y deltaY: Double)
1 2 3 4 5 6
Beginning of method name
First parameter name
First parameter type
Second part of method name
Second parameter name
Second parameter type
In this example, the method is actually called moveByX:y: The equivalent Objective C method definition would look like this.
- (void)moveByX:(Double)deltaX y:(Double)deltaY
When calling this method, the second part of the name is included alone with the rest of the arguments.
var dub = Double(0.5)
moveByX(dub, y: dub)
In your example,
y is the external parameter name,
deltaY is the local parameter name, and
Double is the type of the parameter.
If you are familiar with Objective-C, this corresponds to a method with the following declaration:
-(void)moveByX:(double)deltaX y:(double)deltaY;
Methods in swift have both an external parameter name and a local parameter name. External is defined first then external, if only one is defined swift compiler puts in the defaults.
Swift gives the first parameter name in a method a local parameter name by default, and gives the second and subsequent parameter names both local and external parameter names by default.
In the example, "y" is the external parameter used when calling the method, "deltaY" is the variable name used in the internal calculations of that function.
You can also use _ to signify that you don't want a parameter to have an external name.
# is used for shorthand when both your external and internal name are the same.
Examples
1)
func exampleFunction(externalVarName1 localVarName1: Int, externalVarName2 localVarName2: Int) {}
is called like this:
exampleFunction(externalVarName1: 0, externalVarName2: 0)
2)
func exampleFunction2(autocompleteHintName: Int, autocompleteHintName2: Int) {}
is called like this
exampleFunction2(0, 0)
3)
func exampleFunction3(#nameForBoth: Int, #nameForBoth2: Int) {}
is called like this
exampleFunction3(nameForBoth: 0, nameForBoth2: 0)
4)
func exampleFunction4(nameForBoth nameForBoth: Int, nameForBoth2 nameForBoth2: Int) {}
is the same as 3) but throws a warning that the # shorthhand can be used. called like this
exampleFunction4(nameForBoth: 0, nameForBoth2: 0)
5)
func exampleFunction5(_: Int, _: Int) {}
is called like this
exampleFunction5(0, 0)
deltaX and deltaY are the parameter names when you are writing the function. However, when you call the function it will be called as movebyX(val, y: val) where val is replaced by the Double you are passing into the function. The y in the middle is essentially to help the readability of the function when it is called and is common practice in swift to make your code as readable as possible (the person calling your function can easily tell what each parameter is without looking at the function header).