Alc
(Alc)
1
In the following code, why does _something() not work? I get this
error: missing argument for parameter #1 in call
I am concluding that assigning a function to a variable removes the default value of a parameter? Can anyone explain to me why / how this is beneficial and / or link me references when I can read more about this?
func something(_ i: Int? = nil) {
print(i == nil ? "Optional Int" : "Int")
}
something(1) // Int
something(nil) // Optional Int
something() // Optional Int
let _something = something
_something(1) // Int
_something(nil) // Optional Int
_something() // error: missing argument for parameter #1 in call
Output of swift --version
swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
Target: arm64-apple-macosx14.0
Edit:
If I give a name to the parameter then I get the following. Why did I lose the name information here? I can call it without the name _something(1) instead of _something(i: 1), but I am failing to understand the reasoning and benefits (or lack of?) in this behavior.
func something(i: Int? = nil) {
print(i == nil ? "Optional Int" : "Int")
}
something(i: 1) // Int
something(i: nil) // Optional Int
something() // Optional Int
let _something = something
// _something(i: 1) // error: extraneous argument label 'i:' in --- correct way now is _something(1)
// _something(i: nil) // error: extraneous argument label 'i:' in --- correct way now is _something(nil)
// _something() // error: missing argument for parameter #1 in --- correct way now ???
1 Like
jrose
(Jordan Rose)
2
Yes, the default is attached to the declaration and gets lost when you convert it to an arbitrary value. Not doing so would either mean introducing a specific type for each function—Rust does this, though it doesn't have default values—or complicating closure types quite a bit!
(One thing that would be reasonable to do is allow specifying an explicit type to apply the default up front when converting to a function value. Today you have to use a full closure expression to do that.)
2 Likes
Kyle-Ye
(Kyle)
3
I tried it but it seems we still can't do it on Swift 5.9.2
let s1: (_ i: Int?) -> Void = something
s1(1)
s1(nil)
let s2: (_ i: Int) -> Void = something
s2(1)
// ❌ Default argument not permitted in a tuple type
let s3: (_ i: Int? = nil) -> Void = something
1 Like
jrose
(Jordan Rose)
4
Right, you have to write let s2 = { something() } if you want to leave the argument out. There's no way to have the default in the function type, because that would significantly complicate the implementation, even if it would be convenient.
3 Likes
tera
5
While we are on this, the following would be also nice to have:
// NOT current Swift:
func something(i: Int? = nil) { ... }
let s: () -> Void = something // ✅
1 Like