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?










share|improve this question






















  • 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 how JSONEncoder works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…
    – Stephen H. Gerstacker
    Nov 19 at 19:19















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?










share|improve this question






















  • 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 how JSONEncoder works with these constraints: github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…
    – Stephen H. Gerstacker
    Nov 19 at 19:19













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?










share|improve this question













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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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 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


















  • 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 how JSONEncoder 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












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.






share|improve this answer





















  • 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











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















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

























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.






share|improve this answer





















  • 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















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.






share|improve this answer





















  • 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













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.






share|improve this answer












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.







share|improve this answer












share|improve this answer



share|improve this answer










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 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


















  • 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
















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


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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





















































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







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen