i cannot understand a method behaviour - swift

func mymethod(getno:Int)->(myval :Int,defaults :Int){
return (getno,8)
}
print(mymethod(getno: 2))
the output for the above program is
my val is 2 default is 8
ok, i can understand above program
but the below method is doubtful for me
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
i can't understand this line (var increment=makeIncrementer()) what's happening there ?
Is there somebody who can explain me this briefly?

makeIncrementer returns a function that accepts an Int and return an Int , so this
var increment = makeIncrementer()
makes increment variable to be equal to
func addOne(number: Int) -> Int {
return 1 + number
}
so increment(7) = addOne(7)
You may read Functions chapter in Swift book

You are not alone. I found it hard to wrap my head around this when I first started as well :)
What you are seeing is "a function returning another function". Think of functions as black boxes that take stuff in and spit stuff out. Now imagine passing these around as if they were values like 10 or "Hello".
makeIncrementer returns a function. Which function? This:
func addOne(number: Int) -> Int {
return 1 + number
}
See the line return addOne? That is not calling the function, but returning it!
So when you assign the return value of makeIncrementer to increment:
var increment = makeIncrementer()
increment now has the value of addOne. Calling increment would be the same as calling addOne. The above line is syntactically no different from:
var myString = getMyString()
The difference is that you are working with functions instead of strings.
Now you understand why increment(7) is 8.
If you want to burn your brain more, try looking up currying functions.

Related

(Swift) nested function, function as return, argument

Regarding the code below, I was wondering how nested functions such as stepForward, stepBackward, when they are actually called through 'moveNearerToZero(currentValue), take currentValue as their arguments.
According to the definition of the function chooseStepFunction, the return type is (Int) -> Int. Then, is it because of the parenthesis around Int that the nested functions are able to take currentValue as their arguments?
I can't undesrtand how the value of -4 of currentValue is captured in two nested functions.
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
Functions in Swift are first class citizens. This means that functions can be passed around or stored like a variable, just like any other swift type.
Anything that follows the first -> is the type being returned by that method. In this case chooseStepFunction returns another method that takes one parameter (Int) and returns one value (Int). The parenthesis around the first Int, mean that it's an input parameter.
With that in mind, moveNearerToZero is function that takes one Int and returns another Int. To call that method, you then simply do moveNearerToZero(1) and so on.
I highly recommend you read Apple's section on functions to better understand how functions can be used or passed around.
https://docs.swift.org/swift-book/LanguageGuide/Functions.html
chooseStepFunction(backward: currentValue > 0) returns "stepForward" function. In "stepForward" function as the value is incremental by 1. So, first -4 is getting printed than -3(-4+1) is getting printed and so on until currentValue reaches 0 where the while loop terminates.

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.

Are ++ and +=1 exactly the same?

I just switch to Swift for couple days and I notice that the postfix and prefix ++ and -- will be removed in Swift 3. I have done some research and according to the announcement on the Swift website, the operator ++ and -- will be replaced by += 1 and -= 1. Link here New Features in Swift 2.2
I have a piece of code that work just fine with the old version of Swift. When I change from return counter1++ which is my original code to return counter1 += 1 and an error pops up saying
No '+=' candidates produce the expected contextual type 'Int'
Here is my example
func countingCounter() -> (() -> Int){
var counter1 = 0
let incrementCounter1: () -> Int = {
return counter1+=1 //original is counter1++
}
return incrementCounter1
}
I have tried to work this out but still stuck.
It clearly states in the Apple docs, copied here for your convenience:
NOTE
The compound assignment operators do not return a value. For example, you cannot write let b = a += 2.
No, the ++ operator is NOT the same as +=.
As said in my comment here is how you have to write it now to replace the postfix ++. ANother way would be to use an intermediary variable if you don't like the -1 thing.
let incrementCounter1: () -> Int = {
counter1+=1 //original is counter1++
return counter1-1;
}
No, they aren't identical, ++ and -- increment (or decrement) and return, += and -= add (or subtract) an amount in a simple to read short form, but they don't return anything.
So, you need to separate the value change from the value usage. Which is the whole point of the deprecation really - to make your code easier to read and maintain.
No they aren't identical, you have to increment first, then return the value.try this.
func countingCounter() -> (() -> Int){
var counter1 = 0
let incrementCounter1: () -> Int = {
counter1 += 1
return counter1
}
return incrementCounter1
}
Practicing necromancy here, but nobody mentioned defer yet - here's a slightly more elegant alternative to #Walfrat's method you may like the look of. Defer does the incrementing after returning the value.
let postIncrementCounter1: () -> Int = {
defer { counter1 += 1 } // original is counter1++
return counter1
}

'int?' is not identical to 'Uint8' in swift

func add(numbers: Int...) -> Int?
{
var total:Int?
for i in numbers
{
total += i // >> 'int?' is not identical to 'Uint8' in swift
}
return total
}
numbers is Int, why total can't be assign to Int?
The error you're getting might be a little deceiving. The underlying issue here is that you declared a variable total of type Int?, but never actually assigned it a value. Since total hasn't been given an integer value, it doesn't make sense to try to increment it by i.
You can fix this by initializing the total variable to zero. It's also worth noting that your total and return type do not need to be optionals here, since you're taking a variable number of non-optional Ints as input, meaning that your inputs will always have a total when added together.
If you're dead set on keeping optionals involved here, the following code will work.
func add(numbers: Int...) -> Int? {
var total: Int? = 0
for i in numbers {
total! += i
}
return total
}
Notice that the variable total is being forcibly unwrapped on incrementation. This will crash if total is ever nil (i.e. not given an initial value). But this really isn't necessary. As I explained above, there is no need to use optionals here at all. Instead, I recommend implementing the function like this.
func add(numbers: Int...) -> Int {
var total = 0
for i in numbers {
total += i
}
return total
}
If you're interested in alternatives to your function that are perhaps more Swifty, you can rewrite your entire function like this:
func add(numbers: Int...) -> Int {
return reduce(numbers, 0, +)
}
Your code won't work anyway. You try to add a number to a variable you haven't initialized yet. So the return will always be nil So change that:
var total:Int?
to that:
var total:Int? = 0
But you could also remove the ? because it's not necessary, because you will take non-optional parameters.
var total:Int = 0
Total is not Int is Optional(Int), you have to unwrap for it to become Int
You can do this in 2 ways, faster and safer:
Faster: return total!
Safer:
if let total = total {return total}
Hope this helps, have fun with Swift!

Function taking a variable number of arguments

In this document: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html#//apple_ref/doc/uid/TP40014097-CH2-XID_1
It mentions that when creating for loops we can use the shorthand of 0..3 and 0...3 to replace i = 0; i < 3; ++i and i = 0; i <= 3; ++i respectively.
All very nice.
Further down the document in the Functions and Closures section it says that functions can have a variable number of arguments passed via an array.
However, in the code example we see the ... again.
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
Is this a mistake? It seems to me that a more intuitive syntax would be numbers: Int[].
A few examples down we see another code sample which has exactly that:
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
In case of all arguments are Int numbers: Int[] would be intuitive. But if you have code like this:
func foo(args:AnyObject...) {
for arg: AnyObject in args {
println(arg)
}
}
foo(5, "bar", NSView())
output:
5
bar
<NSView: 0x7fc5c1f0b450>
The type of parameter in sumOf are known as 'variadic' parameter.
The parameters passed are accepted just as a group of elements and is then converted into array before using it within that function.
A great example would be this post.
Passing lists from one function to another in Swift