Precedence of Function Overloading Parameters in Swift
up vote
0
down vote
favorite
I have the following contrived example:
protocol Fooable { }
extension Int: Fooable { }
extension Double: Fooable { }
extension Bool: Fooable { }
func go(value: Any, type: Fooable.Type) -> String {
return "Fooable"
}
func go(value: Any, type: Int.Type) -> String {
return "Int"
}
func go(value: Any, type: Double.Type) -> String {
return "Double"
}
let value1 = 1
go(value: value1, type: type(of: value1)) // Returns "Int"
let value2 = 2.0
go(value: value2, type: type(of: value2)) // Returns "Double"
let value3 = true
go(value: value3, type: type(of: value3)) // Returns "Fooable"
This is the behavior I ultimately want, but what sets this precedence? The more generic, first function can be placed anywhere in the code, giving the same results, so there must be some sort of precedence rules.
Is this outlined anywhere?
swift
add a comment |
up vote
0
down vote
favorite
I have the following contrived example:
protocol Fooable { }
extension Int: Fooable { }
extension Double: Fooable { }
extension Bool: Fooable { }
func go(value: Any, type: Fooable.Type) -> String {
return "Fooable"
}
func go(value: Any, type: Int.Type) -> String {
return "Int"
}
func go(value: Any, type: Double.Type) -> String {
return "Double"
}
let value1 = 1
go(value: value1, type: type(of: value1)) // Returns "Int"
let value2 = 2.0
go(value: value2, type: type(of: value2)) // Returns "Double"
let value3 = true
go(value: value3, type: type(of: value3)) // Returns "Fooable"
This is the behavior I ultimately want, but what sets this precedence? The more generic, first function can be placed anywhere in the code, giving the same results, so there must be some sort of precedence rules.
Is this outlined anywhere?
swift
What is your question? Swift infers the type and method signature and calls corresponding method.
– Mojtaba Hosseini
Nov 19 at 14:29
Why have the second argument on any of these functions? Can you just havefunc go(value: Fooable)
,func go(value: Int)
,func go(value: Double)
?
– NRitH
Nov 19 at 15:43
The exact issue is a bit more complicated to explain. I'm working with theEncodable
/Decodable
protocols, but what I'm wrapping has some pretty ambiguous types and can actually morph values based on the underlying storage type and resulting variable. The above is basically howJSONEncoder
works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…
– Stephen H. Gerstacker
Nov 19 at 19:19
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have the following contrived example:
protocol Fooable { }
extension Int: Fooable { }
extension Double: Fooable { }
extension Bool: Fooable { }
func go(value: Any, type: Fooable.Type) -> String {
return "Fooable"
}
func go(value: Any, type: Int.Type) -> String {
return "Int"
}
func go(value: Any, type: Double.Type) -> String {
return "Double"
}
let value1 = 1
go(value: value1, type: type(of: value1)) // Returns "Int"
let value2 = 2.0
go(value: value2, type: type(of: value2)) // Returns "Double"
let value3 = true
go(value: value3, type: type(of: value3)) // Returns "Fooable"
This is the behavior I ultimately want, but what sets this precedence? The more generic, first function can be placed anywhere in the code, giving the same results, so there must be some sort of precedence rules.
Is this outlined anywhere?
swift
I have the following contrived example:
protocol Fooable { }
extension Int: Fooable { }
extension Double: Fooable { }
extension Bool: Fooable { }
func go(value: Any, type: Fooable.Type) -> String {
return "Fooable"
}
func go(value: Any, type: Int.Type) -> String {
return "Int"
}
func go(value: Any, type: Double.Type) -> String {
return "Double"
}
let value1 = 1
go(value: value1, type: type(of: value1)) // Returns "Int"
let value2 = 2.0
go(value: value2, type: type(of: value2)) // Returns "Double"
let value3 = true
go(value: value3, type: type(of: value3)) // Returns "Fooable"
This is the behavior I ultimately want, but what sets this precedence? The more generic, first function can be placed anywhere in the code, giving the same results, so there must be some sort of precedence rules.
Is this outlined anywhere?
swift
swift
asked Nov 19 at 14:16
Stephen H. Gerstacker
322312
322312
What is your question? Swift infers the type and method signature and calls corresponding method.
– Mojtaba Hosseini
Nov 19 at 14:29
Why have the second argument on any of these functions? Can you just havefunc go(value: Fooable)
,func go(value: Int)
,func go(value: Double)
?
– NRitH
Nov 19 at 15:43
The exact issue is a bit more complicated to explain. I'm working with theEncodable
/Decodable
protocols, but what I'm wrapping has some pretty ambiguous types and can actually morph values based on the underlying storage type and resulting variable. The above is basically howJSONEncoder
works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…
– Stephen H. Gerstacker
Nov 19 at 19:19
add a comment |
What is your question? Swift infers the type and method signature and calls corresponding method.
– Mojtaba Hosseini
Nov 19 at 14:29
Why have the second argument on any of these functions? Can you just havefunc go(value: Fooable)
,func go(value: Int)
,func go(value: Double)
?
– NRitH
Nov 19 at 15:43
The exact issue is a bit more complicated to explain. I'm working with theEncodable
/Decodable
protocols, but what I'm wrapping has some pretty ambiguous types and can actually morph values based on the underlying storage type and resulting variable. The above is basically howJSONEncoder
works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…
– Stephen H. Gerstacker
Nov 19 at 19:19
What is your question? Swift infers the type and method signature and calls corresponding method.
– Mojtaba Hosseini
Nov 19 at 14:29
What is your question? Swift infers the type and method signature and calls corresponding method.
– Mojtaba Hosseini
Nov 19 at 14:29
Why have the second argument on any of these functions? Can you just have
func go(value: Fooable)
, func go(value: Int)
, func go(value: Double)
?– NRitH
Nov 19 at 15:43
Why have the second argument on any of these functions? Can you just have
func go(value: Fooable)
, func go(value: Int)
, func go(value: Double)
?– NRitH
Nov 19 at 15:43
The exact issue is a bit more complicated to explain. I'm working with the
Encodable
/ Decodable
protocols, but what I'm wrapping has some pretty ambiguous types and can actually morph values based on the underlying storage type and resulting variable. The above is basically how JSONEncoder
works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…– Stephen H. Gerstacker
Nov 19 at 19:19
The exact issue is a bit more complicated to explain. I'm working with the
Encodable
/ Decodable
protocols, but what I'm wrapping has some pretty ambiguous types and can actually morph values based on the underlying storage type and resulting variable. The above is basically how JSONEncoder
works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…– Stephen H. Gerstacker
Nov 19 at 19:19
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
The keyword here is "specific". Swift always finds the most specific overload to call.
Swift first infers that value1
is of type Int
, so type(of: value1)
is of type Int.Type
.
Now we've got a Int.Type
as the parameter, Swift looks for an overload that accepts one parameter whose type is exactly Int.Type
. It finds one and calls that. The one that accepts a Fooable.Type
is not called because it can already call a more specific one that accepts exactly a Int.Type
. Here, "specific" means lower down the type hierarchy. Int
is considered more specific than Fooable
because Int
conforms to Fooable
.
value3
is inferred to be of type Bool.Type
. There is not overload that accepts a Bool.Type
, so Swift has to look up the type hierarchy and finds the one that accepts a Fooable.Type
. This is the most specific type that you can pass a Bool.Type
into.
Yeah, it does seem to just go for the most concrete type first and then fall down from there. I just wasn't sure if there was something more formal.
– Stephen H. Gerstacker
Nov 19 at 19:19
For instance, I added aBarable
protocol and applied it to justBool
, then created ago
function forBarable
, and at that point, the compiler considers it too ambiguous.
– Stephen H. Gerstacker
Nov 19 at 19:20
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
The keyword here is "specific". Swift always finds the most specific overload to call.
Swift first infers that value1
is of type Int
, so type(of: value1)
is of type Int.Type
.
Now we've got a Int.Type
as the parameter, Swift looks for an overload that accepts one parameter whose type is exactly Int.Type
. It finds one and calls that. The one that accepts a Fooable.Type
is not called because it can already call a more specific one that accepts exactly a Int.Type
. Here, "specific" means lower down the type hierarchy. Int
is considered more specific than Fooable
because Int
conforms to Fooable
.
value3
is inferred to be of type Bool.Type
. There is not overload that accepts a Bool.Type
, so Swift has to look up the type hierarchy and finds the one that accepts a Fooable.Type
. This is the most specific type that you can pass a Bool.Type
into.
Yeah, it does seem to just go for the most concrete type first and then fall down from there. I just wasn't sure if there was something more formal.
– Stephen H. Gerstacker
Nov 19 at 19:19
For instance, I added aBarable
protocol and applied it to justBool
, then created ago
function forBarable
, and at that point, the compiler considers it too ambiguous.
– Stephen H. Gerstacker
Nov 19 at 19:20
add a comment |
up vote
1
down vote
accepted
The keyword here is "specific". Swift always finds the most specific overload to call.
Swift first infers that value1
is of type Int
, so type(of: value1)
is of type Int.Type
.
Now we've got a Int.Type
as the parameter, Swift looks for an overload that accepts one parameter whose type is exactly Int.Type
. It finds one and calls that. The one that accepts a Fooable.Type
is not called because it can already call a more specific one that accepts exactly a Int.Type
. Here, "specific" means lower down the type hierarchy. Int
is considered more specific than Fooable
because Int
conforms to Fooable
.
value3
is inferred to be of type Bool.Type
. There is not overload that accepts a Bool.Type
, so Swift has to look up the type hierarchy and finds the one that accepts a Fooable.Type
. This is the most specific type that you can pass a Bool.Type
into.
Yeah, it does seem to just go for the most concrete type first and then fall down from there. I just wasn't sure if there was something more formal.
– Stephen H. Gerstacker
Nov 19 at 19:19
For instance, I added aBarable
protocol and applied it to justBool
, then created ago
function forBarable
, and at that point, the compiler considers it too ambiguous.
– Stephen H. Gerstacker
Nov 19 at 19:20
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
The keyword here is "specific". Swift always finds the most specific overload to call.
Swift first infers that value1
is of type Int
, so type(of: value1)
is of type Int.Type
.
Now we've got a Int.Type
as the parameter, Swift looks for an overload that accepts one parameter whose type is exactly Int.Type
. It finds one and calls that. The one that accepts a Fooable.Type
is not called because it can already call a more specific one that accepts exactly a Int.Type
. Here, "specific" means lower down the type hierarchy. Int
is considered more specific than Fooable
because Int
conforms to Fooable
.
value3
is inferred to be of type Bool.Type
. There is not overload that accepts a Bool.Type
, so Swift has to look up the type hierarchy and finds the one that accepts a Fooable.Type
. This is the most specific type that you can pass a Bool.Type
into.
The keyword here is "specific". Swift always finds the most specific overload to call.
Swift first infers that value1
is of type Int
, so type(of: value1)
is of type Int.Type
.
Now we've got a Int.Type
as the parameter, Swift looks for an overload that accepts one parameter whose type is exactly Int.Type
. It finds one and calls that. The one that accepts a Fooable.Type
is not called because it can already call a more specific one that accepts exactly a Int.Type
. Here, "specific" means lower down the type hierarchy. Int
is considered more specific than Fooable
because Int
conforms to Fooable
.
value3
is inferred to be of type Bool.Type
. There is not overload that accepts a Bool.Type
, so Swift has to look up the type hierarchy and finds the one that accepts a Fooable.Type
. This is the most specific type that you can pass a Bool.Type
into.
answered Nov 19 at 15:13
Sweeper
61k967134
61k967134
Yeah, it does seem to just go for the most concrete type first and then fall down from there. I just wasn't sure if there was something more formal.
– Stephen H. Gerstacker
Nov 19 at 19:19
For instance, I added aBarable
protocol and applied it to justBool
, then created ago
function forBarable
, and at that point, the compiler considers it too ambiguous.
– Stephen H. Gerstacker
Nov 19 at 19:20
add a comment |
Yeah, it does seem to just go for the most concrete type first and then fall down from there. I just wasn't sure if there was something more formal.
– Stephen H. Gerstacker
Nov 19 at 19:19
For instance, I added aBarable
protocol and applied it to justBool
, then created ago
function forBarable
, and at that point, the compiler considers it too ambiguous.
– Stephen H. Gerstacker
Nov 19 at 19:20
Yeah, it does seem to just go for the most concrete type first and then fall down from there. I just wasn't sure if there was something more formal.
– Stephen H. Gerstacker
Nov 19 at 19:19
Yeah, it does seem to just go for the most concrete type first and then fall down from there. I just wasn't sure if there was something more formal.
– Stephen H. Gerstacker
Nov 19 at 19:19
For instance, I added a
Barable
protocol and applied it to just Bool
, then created a go
function for Barable
, and at that point, the compiler considers it too ambiguous.– Stephen H. Gerstacker
Nov 19 at 19:20
For instance, I added a
Barable
protocol and applied it to just Bool
, then created a go
function for Barable
, and at that point, the compiler considers it too ambiguous.– Stephen H. Gerstacker
Nov 19 at 19:20
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53376548%2fprecedence-of-function-overloading-parameters-in-swift%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What is your question? Swift infers the type and method signature and calls corresponding method.
– Mojtaba Hosseini
Nov 19 at 14:29
Why have the second argument on any of these functions? Can you just have
func go(value: Fooable)
,func go(value: Int)
,func go(value: Double)
?– NRitH
Nov 19 at 15:43
The exact issue is a bit more complicated to explain. I'm working with the
Encodable
/Decodable
protocols, but what I'm wrapping has some pretty ambiguous types and can actually morph values based on the underlying storage type and resulting variable. The above is basically howJSONEncoder
works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…– Stephen H. Gerstacker
Nov 19 at 19:19