Reputation: 55544
In swift a function can have a optional parameters that have default values such as:
func f(a:Int, b:Int?=nil) {}
f(1);
f(1,2);
I'd like to do this with associated values with an enum. Following from this post about type safe url routes, I'd like to have a route which can take an optional parameter, such as:
enum StopPoint {
case Search(query:String, limit:Int?=nil)
}
However it says I can't have an default value for a parameter in a tuple. However it is possible to have a case such as case Arrivals(stopId:Int)
, yet it is not possible in general to have a tuple with one named parameter.
So is it possible to have an enum with a default parameter, and is the associated value a tuple or not?
Upvotes: 20
Views: 17104
Reputation: 24291
You can do this by creating static functions on the enum that matches the enum case that you want to allow optional parameters for.
enum StopPoint {
case search(query: String, limit: Int?)
static func search(query: String) -> StopPoint {
return .search(query: query, limit: nil)
}
}
This makes it so that you can both provide the limit, or not, using the expected syntax:
let a = StopPoint.search(query: "Foobar")
let b = StopPoint.search(query: "Foobar", limit: 5)
let c = StopPoint.search(query: "Foobar", limit: nil)
func foo(_ stop: StopPoint) { /* ... */ }
foo(.search(query: "Foobar"))
foo(.search(query: "Foobar", limit: 5))
foo(.search(query: "Foobar", limit: nil))
Tested and confirmed working with Swift 4.2
Upvotes: 14
Reputation: 10136
What you can do is:
enum StopPoint {
case Search(query: String, limit: Int?)
init(query: String, limit: Int? = nil) {
self = .Search(query: query, limit: limit)
}
}
let foo = StopPoint(query: "default") // Search("default", nil)
let bar = StopPoint(query: "special", limit: 42) // Search("special", Optional(42))
Upvotes: 14
Reputation: 1784
Perhaps you have already considered this and discounted it: You can come close to the convenience of what you are looking for by creating a static func on the enum:
enum StopPoint {
case Search(query:String, limit:Int?)
static func createSearch(query:String, limit:Int?=nil) -> StopPoint {
return .Search(query: query, limit: limit)
}
}
let myStopPoint = StopPoint.createSearch("my query")
Upvotes: 3
Reputation: 57114
I do not think that is possible. It is simply a neat feature of function
s. Nothing that the actual tuple underneath supports. The docs for Default Parameter Values state:
You can define a default value for any parameter in a function by assigning a value to the parameter after that parameter’s type. If a default value is defined, you can omit that parameter when calling the function.
Enums simply do not to have that feature. You have to explicitly use a different enum element for including optional additional parameters:
enum StopPoint {
case Search(String)
case SearchLimit(String, Int)
}
Enums are quite powerful but not thaaaat powerful. You cannot use default values, you can for example not use a variadic type (maybe even more "restrictions"):
enum StopPoint {
case SearchMult(String...) // causes compile error
}
As to the potentially interesting of the "why"-question: no idea, I am not that deeply involved in the language architecture.
Upvotes: 5