What is the purpose to make a function which return a function? - swift

I was reading Apple doc about swift .
it has an example in which it made a function which returns a function
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
So here my concern is what are advantages of this practice and when to use it?
and if some one can also help me with concept of "A function can take another function as one of its arguments." than that will be so kind
Thanks in advance

Here's a really common case of this that you use all the time, probably without even realizing it.
Instance methods are really just class methods that return closures.
Take String.hasPrefix for example, which has type (String) -> (String) -> Bool.
So String.hasPrefix takes String argument, which is the instance the instance method will act upon, and returns a closure of type (String) -> Bool.
We would usually get this closure by using a form like "The quick brown fox".hasPrefix, but we can also use String.hasPrefix("The quick brown fox"), which is equivalent.
The result of these expressions is the hasPrefix function, bound to the specific instance (the String "The quick brown fox") that it will act upon.
We can then invoke this closure with another String argument, which tells it what prefix to look for.
Here's what you might typically write:
let result = "The quick brown fox".hasPrefix("The") // => True
Let's break that down into steps (with type annotations added for emphasis on the types at play):
import Foundation
let instance: String = "The quick brown fox"
let desiredPrefx: String = "The"
let staticMethod: (String) -> (String) -> Bool = String.hasPrefix
let boundInstanceMethod: (String) -> Bool = staticMethod(instance)
let result: Bool = boundInstanceMethod(desiredPrefx) // => true
equivalent:
import Foundation
let instance: String = "The quick brown fox"
let desiredPrefx: String = "The"
let boundInstanceMethod: (String) -> (String) -> Bool = instance.hasPrefix
let result: Bool = boundInstanceMethod(desiredPrefx) // => true

The benefit of creating a function that returns a function is that the inner function remembers the environment that it was created in. Typically, when you call a function, the variables within that function end when the function finishes. By returning a function, however, you create what is called a closure, and this allows you to hold on to the environment that the closure was created in, so you can use it over and over again.
There are many benefits to being able to accept a function as a parameter to another function. For example, you could create a filter function that accepts an array as its first argument and another function as its second. Then, you could call your filter function and pass it a function that would check each element of the array to see if it was even, and return a new array that only contains even values. You could also call the same filter function with a function that checks each element of an array to see if it is odd, and return a new array containing only odd numbers. This makes the filter function far more flexible than it would otherwise be, and allows you to get away with writing less code. Instead of writing a new, complex function every time you want to filter the elements of an array, and having to maintain a potential multitude of filter functions, you only have to write one.
I hope this helps.

makeIncrementer() have a function addOne(number: Int)
That is only eccessable with in makeIncrementer()
Out side of makeIncrementer() we can not access addOne(number: Int).

Related

Need help understanding how these two statements are equal

Here is a block of code that is equivalent (to my knowledge) to the other.
let f:()->() = brick
where brick is
func brick()->Void{ print("Throw Brick");}
but I can also write it as
let f = {return brick()}
What is this ^ code doing.
The first code I know makes sense to me. This is where I am defining a variable who's type is of the signature ()->() or ()->Void. And then passing the reference of brick function to the variable.
Thanks
Though in both code snippets, f will behave in the same way when you call it, the code snippets are semantically different.
let f:()->() = brick
This assigns the function brick to the let constant f. Note that the type annotation is not required since the compiler knows that brick is a function that takes no parameters and returns Void, so it can infer that f must also be such a function too. Therefore, you can write it as:
let f = brick
Another way to write functions is to use a closure expression. For example, the following closure expression represents a function that calls brick:
{ return brick() }
Since you omitted the in keyword and didn't use any shorthand argument names ($0, $1 etc), the compiler infers that the closure expression takes no arguments. And since brick() returns Void, the closure expression returns Void too - return brick() means "return what brick() returns". The compiler is able to infer the type of the closure expression, so this is valid:
let f = { return brick() }
This assigns a "closure expression that calls simply calls brick() and returns what it returns" to f.
Depending on how you look at it, this is a bit different from let f = brick, where you are directly assigning brick to f. But in the end, in both cases calling f will do the same thing - you will end up calling brick.
The difference is sort of similar to the difference between let x: Double = 1 and let x = cos(0) - x = 1 in both cases, but one of those ways is more direct.
First of all your two versions are not equivalent. This:
func brick()->Void{ print("Throw Brick");}
let f = {return brick()}
is equated by this:
func brick()->Void{ print("Throw Brick");}
func brickCaller() { return brick() }
let f = brickCaller
Whereas, the equivalent of your
let f:()->() = brick
func brick()->Void{ print("Throw Brick");}
would be simply
let f:()->() = { print("Throw Brick") }
with no intermediary call to brick at all.
So, anyway, I'd put it differently from Sweeper's answer. I'd reply that a function can be declared-with-a-name, using func, or be nameless (anonymous), using a mere function body.
So the point is that in each pair of equivalents, one function has a name-and-declaration of its own, with func, and the other function doesn't — its body is simply assigned directly to the variable f.

How come I can create a variable with same name as a function parameter?

In a function, if I'm being passed an int (which is immutable type, i.e let n), how come if I pass this into a function, I can create a var variable of this? Just wondering why swift works this way, and the reason for it .
func checkNum(_ n: Int) -> Bool {
var n = n
}
In this, it let's me do this.
This is called "shadowing" and is allowed in a variety of places because it's convenient for the programmer because it avoids having two similarly named variables in scope. Without this feature, this code would be:
func checkNum(_ n: Int) -> Bool {
var writableN = n
...
}
This raises the possibility of modifying writableN, and then using n again later in the function unintentionally. It also can make the function a bit harder to understand because of the extra variable. (Of course shadowing can also make code more difficult to understand as well, if it's used without care.)
This is very similar to the if let shadowing, such as:
var x: Int? = ...
if let x = x { ... }
This allows you to use x inside the if let as a non-Optional rather than having to come up with some other name for it.
This is a fairly general feature. Whenever there is a new scope, variables can shadow. For example, you can declare variables inside a function that have the same name as properties or globals. You can create scopes inside a function as well
func checkNum(_ n: Int) -> Bool {
var n = n // Shadows previous `let`
do {
let n = 4 // Shadows previous `var`
print(n)
}
return true
}
Used with care, this is helpful. Used too often (as this last example definitely does), it can make the code very confusing.
Your specific case touches on another important aspect of Swift, which is that it tries to control shared mutable state. The n that the function receives is a copy of the integer that was passed. Modifying n would never directly modify the caller's variable. (There's inout to allow this, but it's subtle. It does't share state. It copies the value in, and on return, copies the value back out.)
Since n isn't shared with the caller, Swift makes this very explicit by making it immutable. If you want to modify it, you need to explicitly make another copy, and var n = n does that.
'var' as a parameter attribute has been deprecated in Swift 3 so that is no longer possible. You can get a similar behaviour by using an inout parameter
func checkNum(_ n: inout Int) -> Bool {
n + 1
}
Remember to call the function by passing the parameter like this: checkNum(&n)

How does a function that returns a function work?

I'm reading Apple's book about Swift and stumbled upon this piece of code, which I after many tries couldn't understand. As far as I understand, this function returns a function. The two last lines of code, as well as all the code, though, are totally bewildering. And how we can assign a function to a variable (the seventh line)? Thank you.
I've typed it myself into the Playground but still don't get it.
func makeIncrement () -> ((Int) -> Int){
func addOne (number: Int) -> Int{
return 1 + number
}
return addOne
}
var increment = makeIncrement()
increment(7)
Functions can be considered objects in Swift (or as first class functions - worth researching).
Therefore may be assigned to variables and to object properties.
So in your code makeIncrement simply returns the function addOne as a variable.
var increment = makeIncrement() can just be seen as assigning the returned function from makeIncrement as a variable (or function object) increment.
We can then freely call the increment function as we would call addOneor any other function really.
A function is something with optional input and a return type. If you alt-click on the var increment you will see that increment is of type ((Int) -> Int). This means that you can input an Int and will return an Int. This is then done in the last line by calling this function.
If you know object-oriented programming, you will know that you can always pass objects around, which also have functions. In this way, in your code, it is doing the same but now we are omitting the object.

Very confused, how and when the arguments of the nested function get called and passed value in?

The code example comes from the office swift document
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sort(backwards)
backwards function had been used as the argument of the method sort(_:).
The function backwards returns boolean values. However, when I tried this names.sort(true) I've got an error from the compiler!
Why there are no errors in the example code?
Another question is, what's going on with s1 and s2 as the arguments? When did they get called? How the strings in names array get passed into them?
The function backwards returns boolean values, however, when I tried this names.sort(true)
The sort method being used is actually the sort(isOrderedBefore: (Element, Element) -> Bool) method which takes a comparison function as a parameter. The function has to take the particular set of parameters specified in the interface, i.e. a function that takes two Element parameters and returns a Bool.
As gnasher explained, you're getting an error because true is a value, not a function. You could write a function that returns true though, and that should work. Using Swift's trailing closure syntax, you could write:
names.sort() {return true}
That obviously wouldn't be very useful for actual sorting, but it shows how to make your example work.
what's going on with s1 and s2 as the arguments? When did they get called? How the strings in names array get passed into them?
That's the job of the sort method. It's an instance method belonging to ArraySlice, and it compares the elements in the slice two at a time to determine how they should be ordered. The actual comparison is done using the comparison method that you pass in, so that you can use the same sort method to sort your array using any sort order you can dream up. Try doing this:
let names = ["Harry", "David", "Susan", "Alice"]
let sortedNames = names.sort() {
print($0, $1)
return $0 < $1
}
And you should see a list of output lines as sort() calls your comparison method repeatedly.
"true" isn't a function comparing two strings. When you sort an array of strings, you need a function comparing two strings.

Mutate function parameters in Swift

Is it possible mutating what variables passed as arguments to a function, point to, as their value, within the scope of that function, in Swift?
func exampleFunction(value: String, index: Int) -> Bool {
value = "Changed Value" // Error
index = 3 // Error
return true
}
Calling it by:
var flag = exampleFunction("Passed Value", 2)
Is it possible to mutate the arguments passed as parameters, while within the scope of exampleFunction? if not, is there any other way to do this? Because using this we only change value of temp.
var temp = value
temp = "temp Change"
It seems from your example that you need to change the passed arguments inside the function as a side effect, and need the updated values to be available after the function call. If that's the case, you need to use the inout modifier.
Otherwise, if all you need is to modify the parameters inside of the function call, you can explicitly define them as variables on the function definition:
Using in-out parameters
First, change your function declaration to:
func exampleFunction(inout value: String, index: inout Int) -> Bool
Now, an in-out parameter has a value that is passed in to the function, is modified by the function, and then is passed back out of the function, replacing the original value. For this to work, you can't pass a literal into your function, since there would be nowhere to store the modified value afterwards. In fact, it has to be a variable.
You cannot pass a constant or a literal value as the argument, because constants can't be modified. Hence, change your function call to:
var passed = "passedValue"
var index = 2
var b = exampleFunction(&passed, &index)
After the call, both passed and index will contain the new values, as modified by the function.
Also, note the & before each argument when calling the function. It must be there, to indicate the argument can be modified by the function.
Using variable parameters – Removed in Swift 3
In this case, all you need to do is change your function declaration to use variable parameters, as below:
func exampleFunction(var value: String, var index: Int) -> Bool
Changes made to the arguments inside the scope of the function, aren't visible outside the function or stored anywhere after the function call.
If it's just for the function scope, you can declare your function as
func exampleFunction(var value : String, var index : Int) -> Bool { }
Note - However that was removed in Swift3.
Simply add a var ..
func exampleFunction(value : String, index : Int) -> Bool {
var value = value
var index = index
indeed, the Xcode IDE will autofix that for you.
If your intention is to modify the parameters in their global context, you can use inout.
var Parameter is deprecated and will be removed from Swift 3.0.
If you want to change the parameter inside your function body you should store the passed parameter in some local variable and change it
func exampleFunction(var value: String, var index: Int) -> Bool {
var index = index
...
}
inout Parameter is still there though. So if you want that the changes that you make to the passed parameter should be reflected outside the function body, you should be using inout Parameter.