I wrote this code for testing (learning) purposes in a playground:
import Cocoa
func DoIt(a: Int, b: Int, c :Int = 0) -> Int {
return a + b + c;
}
func DoIt(a: Int, b: Int, c :NSObject) -> Int {
return a * b * c.description.lengthOfBytesUsingEncoding(NSUTF8StringEncoding);
}
And when I used it I got this:
DoIt(4, 5, 6); // result: 20
var obj = NSObject(); // result: NSObject
DoIt(4, 5, obj); // result: 520
I expected the first function DoIt(Int, Int, Int)
called when doing DoIt(4, 5, 6);
but apparently the other is being called. Where did the6
go? It looks like the 6
was implicitly converted into an NSObject
, In objective-c that would rise a warning at least.
Why is this?
Curiously if I make the last c: Int
required (by removing the = 0
) then it works as expected.
DoIt(4, 5, 6); // result: 15
var obj = NSObject(); // result: NSObject
DoIt(4, 5, obj); // result: 520
Edit1: Added IR
In case this helps to understand what is going on I issued the following command and the result is in the gist link: https://gist.github.com/nacho4d/94fdb72d8a3fee0c09e5
$ swiftc \
-emit-ir /Users/nacho4d/Desktop/function2/function2/main.swift \
-sdk Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk
From "Functions" in the Swift documentation (emphasis added):
External Names for Parameters with Default Values
In most cases, it is useful to provide (and therefore require) an external name for any parameter with a default value. This ensures that the argument for that parameter is clear in purpose if a value is provided when the function is called.
To make this process easier, Swift provides an automatic external name for any parameter that has a default value. The automatic external name is the same as the local name, as if you had written a hash symbol before the local name in your code.
So your first function declaration
func DoIt(a: Int, b: Int, c : Int = 0) -> Int
is treated by the compiler as
func DoIt(a: Int, b: Int, c c : Int = 0) -> Int
with an external parameter name "c" for the third parameter. This function would have to be called as
DoIt(4, 5, c: 6) // result: 15
But the call
DoIt(4, 5, 6)
does not match the declaration of your first function, only that of the other function
func DoIt(a: Int, b: Int, c :NSObject) -> Int
(and the third argument is automatically bridged to NSNumber
, which is a subclass
of NSObject
). That's why you get the "unexpected" output.
If you change the declaration of the first function to
func DoIt(a: Int, b: Int, _ c : Int = 0) -> Int
(where _
stands for "no external parameter name")
then you will get the expected output:
DoIt(4, 5, 6) // result: 15
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With