Swift Variable Argument [duplicate] - ios

This question already has answers here:
Passing lists from one function to another in Swift
(2 answers)
Passing an array to a function with variable number of args in Swift
(7 answers)
Closed 8 years ago.
In "The Swift Programming Language", Functions and Closures, there is a sample code to calculate the total as below:
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
As part of the following experiment, I tried the following function to calculate the average
func averageOf(numbers : Int...) -> Int {
var argument:Array = numbers
var average = sumOf(argument) / numbers.count
return average
}
However, I get the following error
[Int] is not convertible to Int
I have also tried the following line with no success
var average = sumOf(numbers) / numbers.count
Any idea whats going on underneath? Why is sumOf parameter is treating it as Int instead of an array when the book clearly states that
“Functions can also take a variable number of arguments, collecting
them into an array.”

It seems to me you function is ok if you try to call it properly.
sumOf(25,23,43,23)
But if you would like to call array use this code :
import UIKit
var someInts = [Int]()
someInts.append(8)
someInts.append(6)
someInts.append(6)
someInts.append(3)
someInts.append(5)
func sumOf(numbers: [Int]) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf(someInts)
The main problem that in function you declare parameter not as array but like undefined amount of the integers

Just change definition of method To
func sumOf(numbers: [Int]) -> Int
Instead Of
func sumOf(numbers: Int...) -> Int
Because you are passing array as an argument to func sumOf function, which is not expected as its define.

Related

How to make a custom function with + operator in Swift [duplicate]

This question already has answers here:
Member operator '%' must have at least one argument of type 'ViewController’
(2 answers)
Closed 1 year ago.
I'm looking at this code from rosettacode.org and one of the functions defined within it is this:
class MyClass {
static func + <T>(el: T, arr: [T]) -> [T] {
var ret = arr
ret.insert(el, at: 0)
return ret
}
}
The compiler has this to say about it:
Member operator '+' must have at least one argument of type 'MyClass'
I updated the method to make it it static, as follows:
static func + <T: Sequence>(el: T, arr: [T]) -> [T] {
var ret = arr
ret.insert(el, at: 0)
return ret
}
That doesn't get rid of the compiler error. I tried Googling it, but I'm not coming up with any short, simple answers. Any ideas how I might quell this error?
As explained by #MartinR in the comments, you need to put this function at the top level (NOT inside a class).
import Foundation
// Will compile fine from here as is
func + <T>(el: T, arr: [T]) -> [T] {
var ret = arr
ret.insert(el, at: 0)
return ret
}
class TableGenerator {
// will require at least one argument of the function to be of `TableGenerator` type
}

Can you set a variable equal to a function with a default parameter, using first class functions?

I want to save a function that takes two parameters as a function that only takes one parameter. I know I learned this with functional programming but I can't remember the methodology name or how to implement it.
Example: a methods like this:
func add (a: Int, b: Int) {
return a + b
}
And you can manipulate and save a new method that let’s say only increments a by 1:
let increment = add(b:1)
print(increment(a: 4))
// prints 5
Can you do this in swift?
It seems you're looking for function currying. This was a part of swift in earlier versions but was removed because it added too much complexity inside the compiler. (Like seen here: https://github.com/apple/swift-evolution/blob/master/proposals/0002-remove-currying.md)
I guess the closest you can get to a curried function is if you do something like this:
func add(_ x: Int) -> (Int) -> Int {
return { y in
y + x
}
}
With this you can say:
let add2 = add(2)
print(add2(3)) // prints 5
You are looking for Default Parameter Values
You can assign default values to the parameters. When calling this function if you pass the value to the parameters that passed value will be used else the default value will be used. To use the default value you can avoid the parameter in the function calling
func add(a: Int = 1, b: Int = 1) -> Int {
return a + b
}
print(add(a: 5, b: 5))//prints 10
print(add(a: 4))//prints 5
print(add(b: 4))//prints 5
print(add())//prints 2

How to declare a variable to host multiple values [duplicate]

In The Swift Programming Language, it says:
Functions can also take a variable number of arguments, collecting them into an array.
func sumOf(numbers: Int...) -> Int {
...
}
When I call such a function with a comma-separated list of numbers (`sumOf(1, 2, 3, 4), they are made available as an array inside the function.
Question: what if I already have an array of numbers that I want to pass to this function?
let numbers = [1, 2, 3, 4]
sumOf(numbers)
This fails with a compiler error, “Could not find an overload for '__conversion' that accepts the supplied arguments”. Is there a way to turn an existing array into a list of elements that I can pass to a variadic function?
Splatting is not in the language yet, as confirmed by the devs. Workaround for now is to use an overload or wait if you cannot add overloads.
Here's a work around that I found. I know it's not exactly what you want, but it seems to be working.
Step 1: Declare the function you'd like with an array instead of variadic arguments:
func sumOf(numbers: [Int]) -> Int {
var total = 0
for i in numbers {
total += i
}
return total
}
Step 2: Call this from within your variadic function:
func sumOf(numbers: Int...) -> Int {
return sumOf(numbers)
}
Step 3: Call Either Way:
var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])
It seems strange, but it is working in my tests. Let me know if this causes unforeseen problems for anyone. Swift seems to be able to separate the difference between the two calls with the same function name.
Also, with this method if Apple updates the language as #manojid's answer suggests, you'll only need to update these functions. Otherwise, you'll have to go through and do a lot of renaming.
You can cast the function:
typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])
You can use a helper function as such:
func sumOf (numbers : [Int]) -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumOf (numbers) }
I did this (Wrapper + Identity Mapping):
func addBarButtonItems(types: REWEBarButtonItemType...) {
addBarButtonItems(types: types.map { $0 })
}
func addBarButtonItems(types: [REWEBarButtonItemType]) {
// actual implementation
}
I know this response does not answer your exact question, but I feel its worth noting. I too was starting to play with Swift and immediately ran into a similar question. Manojlds answer is better for your question, I agree, but again, another workaround I came up with. I do happen to like Logan's better too.
In my case I just wanted to pass an array:
func sumOf(numbers: Array<Int>) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])
Just wanted to share, in case anyone else was thinking like me. Most of the time I would prefer pass the array like this, but I don't think the "Swiftly" yet. :)
Swift 5
This is an approach with #dynamicCallable feature that allows to avoid overloading or unsafeBitCast but you should make a specific struct to call:
#dynamicCallable
struct SumOf {
func dynamicallyCall(withArguments args: [Int]) -> Int {
return args.reduce(0, +)
}
}
let sum = SumOf()
// Use a dynamic method call.
sum(1, 2, 3) // 6
// Call the underlying method directly.
sum.dynamicallyCall(withArguments: [1, 2, 3]) // 6

what's the 'Int -> Int' type ? when a function as a return value? [duplicate]

This question already has answers here:
What does the type ((Int) -> Int) mean in Swift?
(3 answers)
Closed 7 years ago.
func makeIncrementer() -> (Int ->Int) {
func addOne(number:Int) ->Int {
return 1 + number
}
return addOne // result`enter code here`:Int -> Int
}
var increment = makeIncrementer() // result:`enter code here`Int -> Int
increment(7) // result`enter code here`8
I can't understand it how to implement !
In swift a function can return another function.
The following statement:
func makeIncrementer() -> (Int ->Int)
means the makeIncrement function will return another function which has an argument type of Int and it returns an Int
In the above case, the makeIncrementer function returns the addOne function and then you are calling it by passing a value of 7. (It is somewhat similar a function that returns a function pointer in C language)
You can read more about these kind of functions here : Function Types as Return Types

How to convert [Int] to Int... in Swift? [duplicate]

This question already has answers here:
Passing an array to a function with variable number of args in Swift
(7 answers)
Closed 7 years ago.
I am executing the tasks in GuideTour Playground for Swift.
And there is a function for sum:
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
And after that there a task:
Write a function that calculates the average of its arguments.
I want to write smth like:
func avg(numbers: Int...) -> Double {
return Double(sumOf(numbers)) / Double(numbers.count)
}
But XCode shows the warning: '[Int]' is not convertible to 'Int'
Does anybody know how to make this convertion?
PS: I know that I can get the solution with Array-parameter. I am interested in the solution with 'Int...' only. It is just the academic interest.
Instead of writing a function to get the sum of your array of Int, use reduce
func avg(numbers: [Int]) -> Double {
return numbers.reduce(0) { $0 + $1 } / Double(numbers.count)
}

Resources