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

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

Related

How to edit function input in Swift?

I am building an idle clicker app in Swift and I am adding in auto clicks through a function. I want to be able to enter the price through the input for the function, but because the input is a constant, I can't add to the cost price by 9% like I want every time the user clicks the upgrade.
For example if I type 50.0 into the initialPrice how would I make it so that it increases by 10% every time the user clicks it.
func upgrade(intialPrice : Float) {
var upgradePrice = intialPrice
AutoClicks += 1
totalClicks = totalClicks - Int(upgradePrice)
upgradePrice = upgradePrice + (upgradePrice * 0.1)
burritoLvl1Label.text = ("$" + "\(Int(upgradePrice))")
}
I am very new to coding so if you see any way I could make this shorter that would be very helpful.
The other answers have suggested using an inout parameter, and while this will work, it is not a pattern I would recommend. Generally it is better to avoid "side effects" in functions and use inout only when there is a very good reason.
The more general approach would be to have a function that returns the new value.
You might also want to consider using a Decimal rather than a Float when dealing with currency.
Similarly, updating the label probably shouldn't be in this function
func upgrade(initialPrice : Decimal) -> Decimal {
autoClicks += 1
totalClicks -= Int(truncating: initialPrice as NSDecimalNumber)
return initialPrice * 1.1
}
You can then call this function like so:
price = upgrade(initialPrice: price)
burritoLvl1Label.text = ("$" + "\(Int(truncating:price as NSDecimal))")
You need to pass the value in as an inout argument to be able to mutate it. You can also make your implementation more concise by using the compound assignment operators, +=, -= and *=. You should also make sure that you conform to the Swift naming convention, which is loweCamelCase for function and variable names (autoClicks) and UpperCamelCase for types.
func upgrade(initialPrice: inout Float) {
autoClicks += 1
totalClicks -= Int(upgradePrice)
upgradePrice *= 1.1
burritoLvl1Label.text = ("$" + "\(Int(upgradePrice))")
}
However, you should be aware that in most cases you should return the mutated value from a function instead of mutating it by passing it in as an inout parameter. It is especially bad practice to mutate some instance variables of your class without passing them into the function explicitly, while modifying some others using an inout argument.
You should make your input parameter as inout.
More info about swift functions.
func upgrade(intialPrice: inout Float) {
var upgradePrice = intialPrice
AutoClicks += 1
totalClicks = totalClicks - Int(upgradePrice)
upgradePrice = upgradePrice + (upgradePrice * 0.1)
burritoLvl1Label.text = ("$" + "\(Int(upgradePrice))")
}
Hope it helps!

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

How does one pass parameters to a function in Swift? Missing argument in call

Swift function parameters not accepted. Missing argument?
Calculate(theA, theB) //error: Missing argument label 'sideB:' in call
func Calculate(sideA: Int, sideB: Int) -> Int {
var ans = sideA + sideB
return ans;
}
You are missing the sideB: in your function call. I didn't want to rewrite your code (since you posted an image) but here's the working function call.
func calcButton(sender: AnyObject) {
let a: Int = 10
let b: Int = 11
calculate(a, sideB: b) //<-- Missing it here
}
func calculate(sideA: Int, sideB: Int) -> Int {
let a = sideA + sideB
return a
}
you might also want to have both variables in the function call so you can do this instead:
func calcButton(sender: AnyObject) {
let a: Int = 10
let b: Int = 11
calculate(sideA: a, sideB: b)
}
func calculate(sideA A: Int, sideB B: Int) -> Int {
return A + B
}
Just an FYI, use tab completion instead of writing out the function. Xcode will let you know all the function variables with placeholders so you can type them in.
you have missed the sideB param name in swift 3 first parameter is optional but second param is Mandatory that _ in there That’s an underscore. It changes the way the method is called. To illustrate this, here’s a very simple function:
func doStuff(thing: String) {
// do stuff with "thing"
}
It’s empty, because its contents don’t matter. Instead, let’s focus on how it’s called. Right now, it’s called like this:
doStuff(thing: "Hello")
You need to write the name of the thing parameter when you call the doStuff() function. This is a feature of Swift, and helps make your code easier to read. Sometimes, though, it doesn’t really make sense to have a name for the first parameter, usually because it’s built into the method name.
When that happens, you use the underscore character like this:
func doStuff(_ thing: String) {
// do stuff with "thing"
}
That means “when I call this function I don’t want to write thing, but inside the function I want to use thing to refer to the value that was passed in.

Don't understand closures example in Swift

I'm trying to learn about swift and closures.
I'm stuck on this example.
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
What is (number: Int) -> Int? Is it a function? Where is it defined?
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html#//apple_ref/doc/uid/TP40014097-CH2-ID1
What does the keyword "in" do? The docs say to use "to separate the arguments and return type from the body". I'm not sure I understand this. Why isn't "in" used to separate "let result = 3 * number" from "return result".
A closure is just a function with the parameters moved inside the brackets, with the keyword in to separate the parameters from the function body. The two following examples define equivalent functions:
func myFunc(number: Int) -> Int {
let result = 3 * number
return result
}
let myClosure = { (number: Int) -> Int in
let result = 3 * number
return result
}
You can actually call them both in exactly the same way:
let x = myFunc(2) // x == 6
let y = myClosure(2) // y == 6
Notice how the second example is exactly the same as the first, only in the first example, the parameters (number: Int) -> Int are outside the brackets, and in the second example the parameters are inside the brackets, followed by the keyword in.
map works by taking an array (numbers, in your example) and creating a new array that is the result of applying the closure function to each element in numbers. So if numbers is [1, 2, 3], the example above will start with 1. It will apply the closure function which will produce a 3 (cuz all it does is multiply the element from the first array by 3). It does that for each element in numbers, until it has produced a new array, [3, 6, 9].
If you wanted to, you could call map using the names of either the above function or the above closure, or by writing it out explicitly inside of map. All of the below examples are totally equivalent:
let numbers = [1, 2, 3]
// Example 1
let times3 = numbers.map(myFunc) // times3 == [3, 6, 9]
// Example 2
let timesThree = numbers.map(myClosure) // timesThree == [3, 6, 9]
// Example 3
let xThree = numbers.map({ (number: Int) -> Int in
let result = 3 * number
return result // xThree == [3, 6, 9]
})
Note that Example 3 is the same as Example 2, only in Example 3 the closure is spelled out explicitly inside of map, whereas in Example 2 the closure has been assigned to a constant called myClosure, and the constant has been supplied to map.
Hope this helps - closures are fun, but confusing.
The function you're calling takes a closure as its parameter:
numbers.map({...})
The closure provided to the function is expected to receive a parameter when it is executed by the function you called. This parameter is defined in your closure:
(number: Int) -> Int in
You may now use the parameter in the contents of the closure
let result = 3 * number
return result
Closures are self-contained blocks of functionality that can be passed around and used in your code.
Syntax:
{(parameterName: ParameterType) -> returnType in
//Statements
}
Practical Scenario: When user want to apply filter and want to select values which is more than 300(in this case) we can use closures to achive this.
var elements: [Int] = [Int]() //Declaring Empty array
elements = [1001, 999, 555, 786, 988, 322, 433, 128, 233, 222, 201, 276, 133]
var filteredElements = elements.map({(num: Int) -> Int? in
return num > 300 ? num : nil
})
output:
[Optional(1001), Optional(999), Optional(555), Optional(786), Optional(988), Optional(322), Optional(433), nil, nil, nil, nil, nil, nil]
From Below code you can clearly see we are passing closure to elements.map() function.
Closure:
{(num: Int) -> Int? in
return num > 300 ? num : nil
}
(num:Int) is parameter.
Int? is we are going to return Optional Integer Type.
After in we can write your logic.
You can read more about closure here.

Swift Closure parameters, manipulate by position

How to manipulate the closure parameters by their position in Swift.
I've tried in the following way, But, couldn't get the idea behind it, from the documentation.
var additionClosure = { (a : Int , b : Int )-> Int in
return ($0 + $1)
}
var a = 10
var b = 20
println("additionClosure \(additionClosure(a,b))")
Any help would be appreciated..... Well, Thanks in advance.
`The numbered argument format is used for when you don't want to create a named closure.
Example:
import Foundation
func add(a : Int, b : Int) -> Int {
return a + b
}
func test(a : (Int, Int) -> Int) {
println("result: \(a(10,20))")
}
test(add) // Calling test with a named closure
test({$0 + $1}) // Calling test with an anonymous closure
In the first case you define add with two parameters, and give them names a and b. In the second case, you don't even define the name of the closure, just the required functionality using $0 and $1

Resources