Is it possible to give an optional generic parameter a default value?
I'm trying to do something like this:
func addChannel<T>(name: String, data: T? = nil) -> Channel {
}
let myChannel = addChannel("myChannelName")
But I'm getting an error saying
Argument for generic parameter 'T' could not be inferred
Is it just a case of what I'm trying to do being impossible?
In Swift, we can provide default values to function parameters.
An Optional is a variable that can be nil , that's it. If you specify a parameter that is an optional, you have to provide it, even if the value you want to pass is nil . If your function looks like this func test(param: Int?) , you can't call it like this test() .
To make a generic type optional, you have to assign the void as the default value. In the example below, even though the function takes a generic type T, still you can call this function without passing the generic type and it takes void as default.
Swift Generics allows us to create a single function and class (or any other types) that can be used with different data types. This helps us to reuse our code.
It's impossible in the way you've done it. Given just the code above, what type is T
? The compiler, as it says, can't figure it out (neither can I, and I assume you couldn't either because the data's not there).
The solution to the specific question is to overload rather than use defaults:
func addChannel<T>(name: String, data: T?) -> Channel { ... }
func addChannel(name: String) -> Channel { ... }
let myChannel = addChannel("myChannelName")
But it raises the question of what you're doing here. You would think that Channel
should be Channel<T>
. Otherwise, what are you doing with data
? Without resorting to Any
(which you should strongly avoid), it's hard to see how your function can do anything but ignore data
.
With Channel<T>
you can just use a default, but you'd have to provide the type:
func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
let myChannel: Channel<Int> = addChannel("myChannelName")
Otherwise the compiler wouldn't know what kind of channel you're making.
(UPDATE ~ Swift 5.2)
Sometimes you'd like a default type for T
. You can do that with an overload. For example, you might want the default type to be Never
. In that case, you would add an overload like this:
func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
func addChannel(name: String) -> Channel<Never> {
addChannel(name: name, data: Optional<Never>.none)
}
With that, you can have a simpler call:
let myChannel = addChannel(name: "myChannelName") // Channel<Never>
I ran into the same problem. While not being able to use the generic default traditionally — leaving the argument out completely — I prefer the below to implementing overloads:
let myChannel=addChannel("myChannelName", data: Optional<Any>.none)
I use a combination of the existing answers so that I can both call the function without the optional argument and avoid implementing the function twice.
func addChannel(name: String) -> Channel {
addChannel(name: name, data: Optional<Any>.nil)
}
func addChannel<T>(name: String, data: T? = nil) -> Channel {
...
}
As mentioned above you should avoid Any
. In my case I know that T
is an Encodable
so I use this:
struct DefaultEncodable: Encodable {}
func function1(name: String) {
addChannel(name: name, data: Optional<DefaultEncodable>.nil)
}
func function1<T: Encodable>(name: String, data: T? = nil) {
...
}
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