Methods in classes - ios

These two snippets produced the same result. What is numberOfTimes (method?) How do you implement numberOfTimes?
class Counter
{
var count: Int = 0
func incrementBy(amount: Int, numberOfTimes times: Int)
{
count += amount * times
}
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
class Counter
{
var count: Int = 0
func incrementBy(amount: Int, times: Int)
{
count += amount * times
}
}
var counter = Counter()
counter.incrementBy(2, times: 7)

numberOfTimes is not a method, it is an external parameter name. Times is an internal parameter name. Check out this reference for more information.

I'm not sure I understand the question correctly, but numberOfTimes is the external parameter name for the times argument.
The only difference is that in one case you have to call the method as
counter.incrementBy(2, numberOfTimes: 7)
whereas if you leave it out, the local name is automatically used also as external
counter.incrementBy(2, times: 7)
More on the subject in the official docs.

That's an external parameter name, and it identifies the name you use when calling the function, whereas the local parameter name (times in your code) is how is the parameter is referenced from within the function.
Read more about Function Parameter Names

Related

How do closures capture primitive values in local scope [duplicate]

I know there are several related question and moreover I can find many posts in the Internet.
However, I can't understand the fact that closures can hold references. In case of a reference type, it is totally usual and very reasonable, but how about a value type, including struct and enum?
See this code.
let counter: () -> Int
var count = 0
do {
counter = {
count += 1
return count
}
}
count += 1 // 1
counter() // 2
counter() // 3
We can access the value type count through two ways. One is by using count directly and the another is through the closure counter.
However, if we write
let a = 0
let b = a
, in the memory b has of course a different area with a because they are value type. And this behavior is a distinct feature of value type which is different with reference type.
And then backing to the closure topic, closure has the reference to value type's variable or constant.
So, can I say the value type's feature that we can't have any references to value type is changed in case of closure's capturing values?
To me, capturing references to value type is very surprising and at the same time the experience I showed above indicates that.
Could you explain this thing?
I think the confusion is by thinking too hard about value types vs reference types. This has very little to do with that. Let's make number be reference types:
class RefInt: CustomStringConvertible {
let value: Int
init(value: Int) { self.value = value }
var description: String { return "\(value)" }
}
let counter: () -> RefInt
var count = RefInt(value: 0)
do {
counter = {
count = RefInt(value: count.value + 1)
return count
}
}
count = RefInt(value: count.value + 1) // 1
counter() // 2
counter() // 3
Does this feel different in any way? I hope not. It's the same thing, just in references. This isn't a value/reference thing.
The point is that, as you note, the closure captures the variable. Not the value of the variable, or the value of the reference the variable points to, but the variable itself). So changes to the variable inside the closure are seen in all other places that have captured that variable (including the caller). This is discussed a bit more fully in Capturing Values.
A bit deeper if you're interested (now I'm getting into a bit of technicalities that may be beyond what you care about right now):
Closures actually have a reference to the variable, and changes they make immediately occur, including calling didSet, etc. This is not the same as inout parameters, which assign the value to their original context only when they return. You can see that this way:
let counter: () -> Int
var count = 0 {
didSet { print("set count") }
}
do {
counter = {
count += 1
print("incremented count")
return count
}
}
func increaseCount(count: inout Int) {
count += 1
print("increased Count")
}
print("1")
count += 1 // 1
print("2")
counter() // 2
print("3")
counter() // 3
increaseCount(count: &count)
This prints:
1
set count
2
set count
incremented count
3
set count
incremented count
increased Count
set count
Note how "set count" is always before "incremented count" but is after "increased count." This drives home that closures really are referring to the same variable (not value or reference; variable) that they captured, and why we call it "capturing" for closures, as opposed to "passing" to functions. (You can also "pass" to closures of course, in which case they behave exactly like functions on those parameters.)

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 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 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.

Swift Variable Argument [duplicate]

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.

Resources