Difference between functions with / without return Swift - swift

What is the fundamental difference between these 2 functions ?
func sqr(number: Int) {
print (number * number)
}
func sqr1(number: Int) -> Int {
return number * number
}

This is why I basically never teach print to new programmers. People conflate returning values with printing values, because ultimately they all get printed, so there's not much of an evident difference.
Suppose your goal was to evaluate a quadratic equation: a*x^2 + b*x + c.
How would you multiply the x^2 term by a if it doesn't return a value?
func sqr1(number: Int) -> Int {
return number * number
}
let a = 5
let b = 4
let c = 3
let x = 2
let y = 1
let result = a*sqr1(number: x) + b*x + c
print(result)
Trying doing this with sqr(number:), and you'll quickly see that it's impossible.

The first 1 is a void - return function that prints square of a number
The Second 1 is a Int - return function for a square number that returns it to caller
As an illustration sometimes in coding you need to print a value for e.x debugging purposes for beginners sometimes they think it's useless but when you be an experienced you'll know reason of it unlike the 1 that returns the value to callers which makes more sense for all levels

Related

How to properly call another function within a function in swift?

I'm learning an swift and I've written two functions and have tried them on their own they both work well. However when I try to call one function within another one I can't seem to get the desired out-put that I seek.
The task at hand is that one function should print Prime numbers whilst the other is to calculate and check if the number is prime. I am supposed to call the check if number is prime from the print Prime numbers function.
below is my code:
This function calculates whether or not the X:Int is a prime number. It's set to a boolean because I'm supposed to print "true" or "false" in the function below it.
func isPrime(_ x: Int) -> Bool {
if(x%2 == 0 || x%3 == 0){
if(x == 2 || x == 3){
return(true)
}
return(false)
}
else{
//if the number is less than or equal to 1, we'll say it's not prime
if(x <= 1){
return(false)
}
}
return true
}
This piece calculates the printing of the prime number from 1 to n.
func PrintPrimes(upTo n: Int) {
for x in 1...n {
var count = 0
for num in 1..<x {
isPrime(x)
count += 1
}
if count <= 1 {
print(isPrime(x))
}
}
}
This piece only runs twice and i'm not exactly sure why. I don't know if its because i'm not calling it correctly or I'd have to change up some calculations.
All help is appreciated
EDIT:
Here is the original printPrimes() before I decided to call isPrime within the function. This function calculates the prime numbers only and prints them up to n.
func printPrimes(upTo n: Int) {
for x in 1...n {
var count = 0
for num in 1..<x {
if x % num == 0 {
count += 1
}
}
if count <= 1 {
print(x)
}
}
}
Your second routine is printing only two values because it is calling isPrime, but never doing anything conditional on the value returned, but rather incrementing count regardless. And since you’re printing only if count is <= 1, that will happen only for the first two values of n.
But let’s say you were trying to print the prime numbers up to a certain number, you could do:
func printPrimes(upTo n: Int) {
for x in 1...n {
if isPrime(x) {
print(x)
}
}
}
(As a matter of convention, in Swift, when we say “through n”, we’d iterate 1...n, and if someone said “up to n”, we’d iterate 1..<n. But because your original code snippet uses upTo in conjunction with 1...n, I’ll use that here, but just note that this isn’t very consistent with standard Swift API patterns.)
Unfortunately, isPrime is not correct, either. So you’ll have to fix that first. For example, consider 25. That is not divisible by 2 or 3, but isn’t prime, either.
If you look at the original printPrimes that was provided, what it effectively does is say “by how many whole integers less than x is x divisible ... if only divisible by one other number (namely 1), then it’s a prime.” That logic, although not efficient, is correct. You should go ahead and use that inside your isPrime routine. But that “is divisible by 2 or 3” logic is not correct.
You can do it this way, in your printPrimes you can loop up to the number you want and just check if the number is prime by calling the function with the number. But you have to check your isPrime function. Your printPrimes should only do what its name says (print the prime numbers up to n) and all the logic to check if the number is prime should be on your isPrime function.
Also its a good practice to use camelCase on functions, you should rename your function to printPrimes instead of PrintPrimes.
func printPrimes(upTo n: Int) {
for x in 1...n {
if isPrime(x) {
print(x)
}
}
}

How can I search through this array for a specific value then return the other value in the tuple?

I have a large array of (x,y) pairs:
P =
[
(0.0, 500000.09999999998),
(0.001, 18.332777589999999),
(0.002, 18.332221480000001),
(0.0030000000000000001, 18.331665000000001),
(0.0040000000000000001, 18.331108140000001),
(0.0050000000000000001, 18.33055092),
(0.0060000000000000001, 18.32999332),
...
]
I now need to use this in my code. I need to search for a specific x-value and, if the x-value exists, return its corresponding y-value.
Note: If there is a better format I could put my (x,y) pairs in, please feel free to let me know. For example, 2 separate arrays where one holds the x-values and the other holds the y-values. Then I could use the index to find the corresponding y-value or something.
Edit:
A user made a very good point in the comments: how can I reliably compare x == 0.001?
The way I will be using my code is this: I am evaluating a function f(x) at values of x. However, if at a particular value of x there is a y value in the P array, then I need to do an extra subtraction calculation (the details of which are not too important here). The problem, then, is that what if I pass the x value 0.001 in there and the P array does not have a correpsonding y value, but it does have one for 0.001000000009?? Then the code will say there is no value, but in reality it is reasonably close to the intended x value.
I'd suggest to let your array to be an array of CGPoints. It's simply:
A structure that contains a point in a two-dimensional coordinate
system.
However, if you want to get the y values based on searching the x:
let myArray = [
(0.0, 500000.09999999998),
(0.001, 18.332777589999999),
(0.002, 18.332221480000001),
(0.0030000000000000001, 18.331665000000001),
(0.0040000000000000001, 18.331108140000001),
(0.0050000000000000001, 18.33055092),
(0.0060000000000000001, 18.32999332),
]
// this array should contains y values for a given x value
// for example, I search the x value of 0.0
let yValues = myArray.filter { $0.0 == 0.0 }.map { $0.1 }
print(yValues) // [500000.09999999998]
Hope this helped.
A good way of doing this is by declaring this function:
func getValueFromTuples(tupleArr:[(Double,Double)],n:Double)->Double?{
for tuple in tupleArr{
if tuple.0 == n{
return tuple.1
}
}
return nil
}
Then, you can use it like this:
var tupleArray: [(Double,Double)] = [(1.0, 12.0),(2.0,23.0),(3.0,34.0),(4.0,45.0),(5.0,56.0)]
var x:Double = 1.0
print(getValueFromTuples(tupleArr: tupleArray,n:x) ?? "No value found") // 12.0
Where the n argument is the value to be found, the tuple is the key-value pair formed by the numbers and getValueFromTuples returns the value y if x has been found, else nil.
This returns "No value found" if the value does not exist in the array of tuples.
Hope this helps!
Your x value all seem to increase by 0.001. If that is the case, you could also calculate the index and return the y value at this index. This would be a lot more efficient.
func calculateIndex(forX x: Double) -> Int {
let increase = 0.001
return Int(x/0.001)
}
You can use the find method to find the index of the x value and then return the y value. I would multiply your values by 1000 and then compare the Int instead of comparing Double.
func findYValue(forX x: Double) -> Double? {
let multiply = 1000
let x = Int(multiply*x)
if let index = array.index(where: { Int($0.0 * multiply) == x }) {
return array[index].1 //found the y value
}
return nil //x is not in the array
}
Instead of using tuples, I would personally use CGPoint. The class has an x and a y property, which makes your code more readable.
Microsoft gives a very thorough explanation of how to compare 2 doubles. The basic premise is that you need to define a certain level of tolerance. The article the explores how to pick a good tolerance in most cases.
Here's code translated to Swift:
func areEqual(_ lhs: Double, _ rhs: Double, units: Int = 3) -> Bool {
let lValue = Int64(bitPattern: lhs.bitPattern)
let rValue = Int64(bitPattern: rhs.bitPattern)
let delta = lValue - rValue
return abs(delta) <= Int64(units)
}
Test:
var n = 0.0
for _ in 0..<10 {
n += 0.1
}
// n should equal 1 but it does not
print(n == 1.0) // false
print(areEqual(1.0, n)) // true
Back to your problem, it becomes straight forward after you defined how to test for equality in 2 doubless:
let x = 0.003
if let y = p.first(where: { areEqual($0.0, x) })?.1 {
print(y)
}

what does ++ exactly mean in Swift?

i am learning Swift with a book aimed for people with little experience. One thing bothering me is the ++ syntax. The following is taken from the book:
var counter = 0
let incrementCounter = {
counter++
}
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
the book said counter is 5.
but i typed these codes in an Xcode playground. It is 4!
i am confused.
The post-increment and post-decrement operators increase (or decrease) the value of their operand by 1, but the value of the expression is the operand's original value prior to the increment (or decrement) operation
So when you see playground, current value of counter is being printed.
But after evaluation of function, the value of counter changes and you can see updated value on the next line.
x++ operator is an operator that is used in multiple languages - C, C++, Java (see the C answer for the same question)
It is called post-increment. It increments the given variable by one but after the current expression is evaluated. For example:
var x = 1
var y = 2 + x++
// the value of x is now 2 (has been incremented)
// the value of y is now 3 (2 + 1, x has been evaluated before increment)
This differs from the ++x (pre-increment) operator:
var x = 1
var y = 2 + ++x
// the value of x is now 2 (has been incremented)
// the value of y is now 4 (2 + 4, x has been evaluated after increment)
Note the operator is getting removed in the next version of Swift, so you shouldn't use it anymore.
It's always better to just write x += 1 instead of complex expressions with side effects.
The value of counter after your five calls to the incrementCounter closure will be 5, but the return of each call to incrementCounter will seemingly "lag" one step behind. As Sulthan writes in his answer, this is due to x++ being a post-increment operator: the result of the expression will be returned prior to incrementation
var x = 0
print(x++) // 0
print(x) // 1
Also, as I've written in my comment above, you shouldn't use the ++ and -- operators as they will be deprecated in Swift 2.2 and removed in Swift 3. However, if you're interested in the details of post- vs pre-increment operator, you can find good answers here on SO tagged to other languages, but covering the same subject, e.g.
What is the difference between ++i and i++?
It's worth mentioning, however, a point that is relevant to Swift > 2.1 however, and that don't really relate to the ++ operator specifically.
When you initiate the closure incrementCounter as
var someOne : Int = 0
let incrementCounter = {
someInt
}
The closure is implictly inferred to be of type () -> Int: a closure taking zero arguments but with a single return of type Int.
let incrementCounter: () -> Int = {
return someInt
}
Hence, what you seemingly "see" in you playground is the unused (non-assigned) return value of the call to incrementCounter closure; i.e., the result of the expression incrementCounter().
Whereas the value of counter is never really printed in the right block of your playground (unless you write a line where the result of that line:s expression is counter).
++ and -- before the identifier add/subtract one, and then return its value.
++ and -- after the identifier return its value, and then add/subtract 1.
They were removed in Swift 3.0, but you can add them back:
prefix operator --
prefix operator ++
postfix operator --
postfix operator ++
prefix func ++(_ a : inout Int) -> Int {
a += 1
return a
}
prefix func --(_ a : inout Int) -> Int {
a -= 1
return a
}
postfix func ++(_ a: inout Int) -> Int {
defer { a += 1 }
return a
}
postfix func --(_ a: inout Int) -> Int {
defer { a -= 1 }
return a
}
var a = 11
print(a++) // 11
print(a) // 12
var b = 5
print(--b) // 4
print(b) // 4
even though there are a lot of answers and all of them are clear i added this snippet to show you how to replace your code with 'new' syntax, where ++ and or -- are deprecated. at first your own code
var counter = 0
let incrementCounter = {
counter++
}
let i0 = incrementCounter() // 0
let i1 = incrementCounter() // 1
// .....
how to rewrite it in future Swift's syntax? lets try the recommended replacement ...
var counter = 0
let ic = {
counter += 1
}
let i0 = ic() // () aka Void !!!
let i1 = ic() // ()
but now the result of ic() is Void! Hm ... OK, the next attempt could looks like
var counter = 0
let ic = {
counter += 1
return counter
}
but now the code doesn't compile with error: unable to infer closure return type in current context :-), so we have to declare it (it was not necessary in our original version)
var counter = 0
let ic:()->Int = {
counter += 1
return counter
}
let i0 = ic() // 1
let i1 = ic() // 2
// .....
it works, but the results are not the same. that is because in original code ++ operator was used as post-increment operator. so, we need another adjustment of our 'new' version
var counter = 0
let ic:()->Int = {
let ret = counter
counter += 1
return ret
}
let i0 = ic() // 0
let i1 = ic() // 1
// .....
yes, i would like to see my familiar unary ++ and / or -- will be also in the future versions of Swift
The thing which you are doing is post increment.
First Learn the difference between Pre & Post Increment
In Post Increment, the value counter after increment contains incremented value (i.e 5)
but if we return, then it will contain old value (i.e 4).
In Pre Increment, both the value and return value is incremented.
Lets look into your code now,
counter++ makes a copy, increases counter, and returns the copy (old value).
so if you print counter it will have incremented value (i.e 5) but, if you return counter (i.e your doing so with incrementCounter) it contains the old value (i.e 4).
because of which incrementCounter only showing upto 4.
CHECK OUTPUT
Solution :
change counter++ to ++counter
CHECK OUTPUT

Why can't I divide integers in swift?

In the Swift "Tour" documentation, there's an exercise where you build on the following function to average a set of numbers:
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
I can make this work using something like the following:
func averageOf(numbers: Double...) -> Double {
var sum: Double = 0, countOfNumbers: Double = 0
for number in numbers {
sum += number
countOfNumbers++
}
var result: Double = sum / countOfNumbers
return result
}
My question is, why do I have to cast everything as a Double to make it work? If I try to work with integers, like so:
func averageOf(numbers: Int...) -> Double {
var sum = 0, countOfNumbers = 0
for number in numbers {
sum += number
countOfNumbers++
}
var result: Double = sum / countOfNumbers
return result
}
I get the following error: Could not find an overload for '/' that accepts the supplied arguments
The OP seems to know how the code has to look like but he is explicitly asking why it is not working the other way.
So, "explicitly" is part of the answer he is looking for: Apple writes inside the "Language Guide" in chapter "The Basics" -> "Integer and Floating-Point Conversion":
Conversions between integer and floating-point numeric types must be
made explicit
you just need to do this:
func averageOf(numbers: Int...) -> Double {
var sum = 0, countOfNumbers = 0
for number in numbers {
sum += number
countOfNumbers++
}
var result: Double = Double(sum) / Double(countOfNumbers)
return result
}
You are assigning the output of / to a variable of type Double, so Swift thinks you want to call this function:
func /(lhs: Double, rhs: Double) -> Double
But the arguments you're passing it are not Doubles and Swift doesn't do implicit casting.
that may be helpful:
func averageOf(numbers: Int...) -> Double {
var sum = 0, countOfNumbers = 0
for number in numbers {
sum += number
countOfNumbers++
}
var result: Double = Double(sum) / Double(countOfNumbers)
return result
}
OR
overloading the / operator can be also a solution, like in Swift 4.x that would look like:
infix operator /: MultiplicationPrecedence
public func /<T: FixedWidthInteger>(lhs: T, rhs: T) -> Double {
return Double(lhs) / Double(rhs)
}
I don't find a necessity for a Forced Division. Normal division operator works though.
In the following code,
func average(numbers:Int...)->Float{
var sum = 0
for number in numbers{
sum += number
}
var average: Float = 0
average = (Float (sum) / Float(numbers.count))
return average
}
let averageResult = average(20,10,30)
averageResult
Here, two float values are divided, of course after type casting as i am storing the result in a float variable and returning the same.
Note: I have not used an extra variable to count the number of parameters.
"numbers" are considered as array, as the functions in Swift take a variable number of arguments into an array.
"numbers.count" (Similar to Objective C) will return the count of the parameters being passed.
Try this but notice swift doesn't like to divide by integers that are initialized to zero or could become zero so you must use &/ to force the division. this code is a little verbose but it is easy to understand and it gives the correct answer in integer not floating point or double
func sumOf(numbers: Int...) -> Int {
var sum = 0
var i = 0
var avg = 1
for number in numbers {
sum += number
i += 1
}
avg = sum &/ i
return avg
}
sumOf()
sumOf(42, 597, 12)
There's no reason to manually track of the number of arguments when you can just get it directly.
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
let average = sum &/ numbers.count
return average
}
sumOf()
sumOf(42, 597, 12)
Way late to the party, but the reason is because when dividing two INTs in Swift the result is always an INT.
The Compiler does this by truncating the value after the decimal-point (i.e. 5 / 2 = 2; the actual result should be 2.5).
To get the true average (the non-truncated value) you need to cast to a Double, so that the value after the decimal is retained. Otherwise, it will be lost.

Variable And Function Calls On Lines By Themselves In Swift

I'm reading the iBook The Swift Programming Language and seeing a convention that I don't understand and hasn't been explained in the book: variable and functions followed by a single line with the variable or function name by itself.
For example:
var n = 2
while n < 100 {
n = n * 2
}
n
var m = 2
do {
m = m * 2
} while m < 100
m
And:
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()
What is the purpose of these lines where the variable or function name are on a line by themselves?
TIA
The purpose is for "Playground" Demonstrations. For example, if you put that code into playground. The window on the right will show result of the execution of the function.
If you were in a traditional project, you would likely do:
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
var someInt = returnFifteen()
println(someInt)
However, this is unnecessary in Playground:
Notice the right side.
When you are using Swift in the playground, the output display on the right hand side is not actually a console output more so just an output of whatever variable is on that line, or the number of times a loop runs.
So they are placing the variable/function on it's own line so that when you paste that into Playground you will see what the result is.