Function taking a variable number of arguments - swift

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

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.

Why does Swift think that my array is a function?

// Complete the miniMaxSum function below.
func birthdayCakeCandles(arr: [Int]) -> Int {
let a = arr.sorted
let highest = a().last!
return 0
}
birthdayCakeCandles(arr: [1, 7, 3, 12, 5])
I tried to create a sorted array "a" from an unsorted array "arr", to solve a problem from HackerRank. But compiler gives following error:
main.swift:5:19: error: function 'a' was used as a property; add () to
call it
let highest = a.last!
^
()
Why does it think, that "a" is a function?
error: function 'a' was used as a property; add () to call it
Swift doesn't think that your array is a function. Xcode just tells you, that sorted is a method and you have to call it with () at the end
let a = arr.sorted()
let a = arr.sorted
Why does it think, that "a" is a function?
Because that is just what it is. sorted is the name of a function. So a is now the sorted function.
What you want is for a to be the result of calling a function. But every function call involves parentheses, e.g. sorted(). You have no parentheses.
In short that line of your code talks about sorted. But it never calls sorted. It just renames it.
arr.sorted evaluates to a method of [Int]. If you want a sorted copy of the array call that method:
func birthdayCakeCandles(arr: [Int]) -> Int {
let a = arr.sorted()
let highest = a.last!
return 0
}
Otherwise, the compiler is right: a contains a function: The sorted method.
I believe what you want to do is the following:
func birthdayCakeCandles(arr: [Int]) -> Int {
return arr.max() ?? 0
}
In your code, a is not an array, it is a function with the following signature () -> [Int], because arr.sorted is an instance method. You can check the type of a variable by Alt + clicking on the variable in Xcode. To execute this function you need to invoke it using (). Which you are doing in the following line. The output of a() is an array of integers, on which you are calling the last property.
If your arr is empty, .last! will cause an error/app crash, since you'd be unwrapping nil (there is no last element in an empty array). This is why in the suggested code above, I've used the nil-coalescing operator ??, which would guarantee that the function would return 0 if the array arr is empty.
For more in-depth reading on instance methods, have a look here.

i cannot understand a method behaviour

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.

inout Declarations for Type Decoration

I have a question according usage of the inout in Swift 3.
As i understand inout is quite expensive operation for use.
And there is question when and why it is better to use inout declaration?
regular function:
func double(input: Int) {
var input = input
input = input * 2
}
inout declaration use:
func double(input: inout Int) {
input = input * 2
}
Be careful, this is a classic trap! :)
Your two functions are not doing the same thing, so one is not "better" than the other.
Your first one:
func double(input: Int) {
var input = input
input = input * 2
}
does nothing.
Because with var input = input you are making a copy of the input value, so when you do input = input * 2 you are just modifying the local copy, and since you don't return it, it is discarded and this function has no effect in the end.
Your second one:
func double(input: inout Int) {
input = input * 2
}
does something: it modifies the original value because inout is a way of passing a value by reference. No need to make a copy and return it: the variable itself, the one you pass to the function, will be changed.
Note: I suggest you read Martin R's excellent link where inout is very well explained: https://stackoverflow.com/a/34486250/1187415.

Simple Pointer Operations in Swift?

Let's say I do the following in C++:
int i = 1;
int* ptr = &i;
*ptr = 2;
cout << i << '\n';
And I want to do something similar in swift. Could I do the following?
var i : Int = 1
var iptr : UnsafeMutablePointer<Int> = &i
iptr.memory = 2
print(i)
And achieve the same result?
Yes-ish.
You can't do it exactly as you've attempted in the question. It won't compile. Swift won't let you directly access the address of a value like this. At the end of the day, the reason is mostly because there's simply no good reason to do so.
We do see the & operator in Swift however.
First of all, there is the inout keyword when declaring function parameters:
func doubleIfPositive(inout value: Float) -> Bool {
if value > 0 {
value *= 2
return true
}
return false
}
And to call this method, we'd need the & operator:
let weMadeARadian = doubleIfPositive(&pi)
We can see it similarly used when we have a function which takes an argument of type UnsafeMutablePointer (and other variants of these pointer structs). In this specific case, it's primarily for interoperability with C & Objective-C, where we could declare a method as such:
bool doubleIfPositive(float * value) -> bool {
if (value > 0) {
value *= 2;
return true;
}
return false;
}
The Swift interface for that method ends up looking somethin like this:
func doubleIfPositive(value: UnsafeMutablePointer<Float>) -> Bool
And calling this method from Swift actually looks just like it did before when using the inout approach:
let weMadeARadian = doubleIfPositive(&pi)
But these are the only two uses of this & operator I can find in Swift.
With that said, we can write a function that makes use of the second form of passing an argument into a method with the & operator and returns that variable wrapped in an unsafe mutable pointer. It looks like this:
func addressOf<T>(value: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T> {
return value
}
And it behaves about as you'd expect from your original code snippet:
var i: Int = 1
var iPtr = addressOf(&i)
iPtr.memory = 2
print(i) // prints 2
As noted by Kevin in the comments, we can also directly allocate memory if we want.
var iPtr = UnsafeMutablePointer<Int>.alloc(1)
The argument 1 here is effectively the mount of space to allocate. This says we want to allocate enough memory for a single Int.
This is roughly equivalent to the following C code:
int * iPtr = malloc(1 * sizeof(int));
BUT...
If you're doing any of this for anything other than interoperability with C or Objective-C, you're most likely not Swifting correctly. So before you start running around town with pointers to value types in Swift, please, make sure it's what you absolutely need to be doing. I've been writing Swift since release, and I've never found the need for any of these shenanigans.
Like this (not the only way, but it's clear):
var i : Int = 1
withUnsafeMutablePointer(&i) {
iptr -> () in
iptr.memory = 2
}
print(i)
Not a very interesting example, but it is completely parallel to your pseudo-code, and we really did reach right into the already allocated memory and alter it, which is what you wanted to do.
This sort of thing gets a lot more interesting when what you want to do is something like cycle thru memory just as fast as doing pointer arithmetic in C.