Suppose that we have several overloaded functions in one class:
func appendToABC(string s: String) -> String {
return "ABC \(s)"
}
func appendToABC(duplicatedString s: String) -> String {
return "ABC \(s)\(s)"
}
And we have some API that gets function as an argument:
func printString(function: (String) -> String) {
print(function("ASD"))
}
How can we pass one of appendToABC functions as an argument to a printString function?
I've thought about wrapping the function with a closure, but it doesn't look nice
printString { appendToABC(duplicatedString: $0) }
This is a known limitation in Swift. There is an open proposal to address it. Currently the only solution is a closure.
Note that this is true of many things in Swift. You also can't refer to properties directly as functions, even though they behave like functions. You must use a closure. And even some free functions cannot be directly passed (print is the most common example).
Related
How can I access the str label inside the function body? If it's impossible then why the compiler doesn't throw an error ?
class Test {
func methodA(str _: String) {
}
func methodB() {
methodA(str: "")
}
}
Using _ for the parameter name means you have no need to use the parameter within the method. The str argument label has no use inside the implementation of the method itself. It's only useful in the calling syntax.
If you actually have a need to use a parameter in a method, don't give it the anonymous name of _. Give it a useful name so it can be referenced in the implementation of the method. Or simply remove the _ so both the parameter name and label are the same.
Either do:
func methodA(str: String) {
// do something with str
}
or something like:
func methodA(str val: String) {
// do something with val
}
In both cases the caller is the same as you currently have:
methodA(str: "")
The only time you would want an anonymous parameter name is if your implementation of the method doesn't actually make use of the parameter. Maybe the implementation isn't finished or over time it's changed and a parameter isn't needed any more and you don't want to update lots of existing code calling the method.
There is a compiler setting to get warnings about unused parameters. If you have an unused parameter, changing the name to _ eliminates the warning.
See Function Argument Labels and Parameter Names in the Swift book (though it doesn't cover this case of anonymous parameter names).
After converting from Swift 2.2 to 3.0 my Array extension does not compile anymore, because it contains a call to global standard library function min<T>(T,T) and shows compiler error extra argument in call.
Here's a simple way to reproduce the error:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return min(first, second) // compiler error: "Extra argument in call"
}
}
I get the same error when adding the same function to an extension of Dictionary, while the exact same code compiles just fine in an extension of other types (e.g. String or AudioBuffer):
Looking at the documentation of Array and Dictionary, I find that there are instance methods on Sequence named public func min() -> Element? and public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?. While both String and AudioBuffer do not have any kind of min(...) function.
Is it possible that this is the reason why I can't call the global function? The compiler can't distinguish between global func min<T>(T,T) and self.min(...) although they have completely different signatures?
Is this a bug or a feature? What am I doing wrong? How can I call min(T,T) correctly inside an Array extension?
I see no reason why the compiler shouldn't be able to resolve this function call, therefore I would consider it a bug (it has already been filed – see SR-2450).
It seems to occur whenever attempting to call a top-level function with the same name, but unambiguously different signature to a method or property that's accessible from the same scope in a given type (instance or static).
An even simpler example would be:
func foo(_ a: Int) {}
struct Foo {
func foo() {} // or static func foo() {}, var foo = 0, static var foo = 0
func bar() {
foo(2) // error: argument passed to call that takes no arguments
}
}
Until fixed, a simple solution would be to prefix the call with the name of the module in which it resides in order to disambiguate that you're referring to the top-level function, rather than the instance one. For the standard library, that's Swift:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return Swift.min(first, second)
}
}
In Swift 4, the compiler has a better diagnostic for this error (though the fact that it's still an error is a bug IMO):
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
// Use of 'min' refers to instance method 'min(by:)'
// rather than global function 'min' in module 'Swift'
// - Use 'Swift.' to reference the global function in module 'Swift'
return min(first, second)
}
}
Although what's interesting is that the compiler will now also warn on attempting to call a standard library method with the same name as a stdlib top-level function:
extension Array where Element : Comparable {
func smallest() -> Element? {
// Use of 'min' treated as a reference to instance method in protocol 'Sequence'
// - Use 'self.' to silence this warning
// - Use 'Swift.' to reference the global function
return min()
}
}
In this case, as the warning says, you can silence it by using an explicit self.:
extension Array where Element : Comparable {
func smallest() -> Element? {
return self.min()
}
}
Although what's really curious about this warning is it doesn't appear to extend to non-stdlib defined functions:
func foo(_ a: Int) {}
struct Foo {
func foo() {}
func bar() {
foo() // no warning...
}
}
After converting from Swift 2.2 to 3.0 my Array extension does not compile anymore, because it contains a call to global standard library function min<T>(T,T) and shows compiler error extra argument in call.
Here's a simple way to reproduce the error:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return min(first, second) // compiler error: "Extra argument in call"
}
}
I get the same error when adding the same function to an extension of Dictionary, while the exact same code compiles just fine in an extension of other types (e.g. String or AudioBuffer):
Looking at the documentation of Array and Dictionary, I find that there are instance methods on Sequence named public func min() -> Element? and public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?. While both String and AudioBuffer do not have any kind of min(...) function.
Is it possible that this is the reason why I can't call the global function? The compiler can't distinguish between global func min<T>(T,T) and self.min(...) although they have completely different signatures?
Is this a bug or a feature? What am I doing wrong? How can I call min(T,T) correctly inside an Array extension?
I see no reason why the compiler shouldn't be able to resolve this function call, therefore I would consider it a bug (it has already been filed – see SR-2450).
It seems to occur whenever attempting to call a top-level function with the same name, but unambiguously different signature to a method or property that's accessible from the same scope in a given type (instance or static).
An even simpler example would be:
func foo(_ a: Int) {}
struct Foo {
func foo() {} // or static func foo() {}, var foo = 0, static var foo = 0
func bar() {
foo(2) // error: argument passed to call that takes no arguments
}
}
Until fixed, a simple solution would be to prefix the call with the name of the module in which it resides in order to disambiguate that you're referring to the top-level function, rather than the instance one. For the standard library, that's Swift:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return Swift.min(first, second)
}
}
In Swift 4, the compiler has a better diagnostic for this error (though the fact that it's still an error is a bug IMO):
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
// Use of 'min' refers to instance method 'min(by:)'
// rather than global function 'min' in module 'Swift'
// - Use 'Swift.' to reference the global function in module 'Swift'
return min(first, second)
}
}
Although what's interesting is that the compiler will now also warn on attempting to call a standard library method with the same name as a stdlib top-level function:
extension Array where Element : Comparable {
func smallest() -> Element? {
// Use of 'min' treated as a reference to instance method in protocol 'Sequence'
// - Use 'self.' to silence this warning
// - Use 'Swift.' to reference the global function
return min()
}
}
In this case, as the warning says, you can silence it by using an explicit self.:
extension Array where Element : Comparable {
func smallest() -> Element? {
return self.min()
}
}
Although what's really curious about this warning is it doesn't appear to extend to non-stdlib defined functions:
func foo(_ a: Int) {}
struct Foo {
func foo() {}
func bar() {
foo() // no warning...
}
}
I'm trying to grasp the concept behind curry functions. Below is the code:
class MyHelloWorldClass {
func helloWithName(name: String) -> String {
return "hello, \(name)"
}
}
I can create a variable that points to the class’s helloWithName function:
let helloWithNameFunc = MyHelloWorldClass.helloWithName
// MyHelloWorldClass -> (String) -> String
My new helloWithNameFunc is of type MyHelloWorldClass -> (String) -> String, a function that takes in an instance of my class and returns another function that takes in a string value and returns a string value.
So I can actually call my function like this:
let myHelloWorldClassInstance = MyHelloWorldClass()
helloWithNameFunc(myHelloWorldClassInstance)("Mr. Roboto")
// hello, Mr. Roboto
Credit: I go this code from this site
What is the benefit of using the above curry function? When would there a need to call a function that takes an instance of its class, that takes the subsequent parameter that was passed.
The problem is that the example given isn't an example of currying exactly. That's why you don't see any value in it.
This is a better example of currying:
class MyHelloWorldClass {
//Function that takes two arguments
func concatenateStrings(string1: String, string2: String) {
return "\(string1)\(string2)"
}
//Curried version of concatenateStrings that takes one argument.
func helloWithName(name: String) -> String {
return concatenateStrings("hello, ", name)
}
}
This is a better example of how function variables are curried functions in Swift: http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/
What's the purpose of "with" keyword in Swift? So far I have found that the keyword can be used if you need to override an existing global function, such as toDebugString.
// without "with" you get "Ambiguous use of 'toDebugString'" error
func toDebugString<T>(with x: T) -> String
{
return ""
}
toDebugString("t")
with is not a keyword - it's just an external parameter identifier. This works as well:
func toDebugString<T>(whatever x: T) -> String
Since the toDebugString<T>(x: T) function is already defined, by using an external parameter you are creating an overload: same function name, but different parameters. In this case the parameter is the same, but identified with an external name, and in swift that makes it a method with a different signature, hence an overload.
To prove that, paste this in a playground:
func toDebugString<T>(# x: T) -> String {
return "overload"
}
toDebugString(x: "t") // Prints "overload"
toDebugString("t") // Prints "t"
The first calls your overloaded implementation, whereas the second uses the existing function
Suggested reading: Function Parameter Names