What does this function actually do? - swift

i am currently trying to do some self learning in swift just for my own interest. in the course i bought it says that we should create a function similar to this one in order to solve my problem. but I'm blankly staring trying to figure out what this function actually does?
func unknown() -> () -> Int {
var x = 0
let z: () -> Int = {
x += 1
return x
}
return z
}

It is a function that returns another function which will return an integer that will be increased everytime you call it:
let afunc = unknown()
let value1 = afunc() // 1
let value2 = afunc() // 2
let value3 = afunc() // 3

The interesting part of this is the return type. () -> Int is a function that returns an Int, which means that unknown returns a function rather than something simple, like a number.
z is then a variable of that same type and is assigned a function definition to be returned.
If you assign the result of unknown to a variable, you can then invoke the returned function.

This implementation of a high order function is an interesting way of defining generators. An infinite sequence-like class would've achieve the same thing, but with more verbosity:
class MySequence {
private var x = 0
func unknown() -> Int {
x += 1
return x
}
}
var seq = MySequence()
let unknown = seq.unknown
print(unknown()) // 1
print(unknown()) // 2
print(unknown()) // 3
// ... and so on
The main difference between the class and the anonymous closure is the storage for x: the closure captures in due to using the variables within its body, while the class declares explicit storage for the property.
Some fancy stuff can result by using high order functions, like a generator for the Fibonacci numbers:
func fibonnaciSequence() -> () -> Int? {
var a = 0, b = 1
return { let c = a; a += b; b = c; return c }
}
let fibo = fibonnaciSequence()
while let f = fibo() {
// this will print forever
// actually not forever, it will stop at some point due to += overflowing
print(f)
}

Related

Is there a way to retrieve directly the value returned from a closure in Swift, with type the return type of the closure and not: () -> Type

This is a question that aims merely at elegance, but is there a way to make something to the following code work in Swift? I know the code does not work, what I want is that the result of the code within the closure is stored in a constant. And the underlying theoretical issue is whether or not it is possible to retrieve the returned value from the closure with type Int and not with type () -> Int.
Thanks a lot for any help or comment!
let tableWithBooleans: [Bool] = Array(repeating: false, count: 10)
tableWithBooleans[0] = true
tableWithBooleans[5] = true
let numberOfTrue: Int = {
var result: Int = 0
for i in 0...9 {
if tableWithBooleans[i] {
result += 1
}
}
return result
}
// I want the code to compile and numberOfTrue to be a constant equal to 2
Use a high-order function instead
let numberOfTrue = tableWithBooleans.reduce(0) { $1 ? $0 + 1 : $0 }
Now if you still want to use your closure code then you should add a () after the closing } since you are calling the code inside {} as a function
let numberOfTrue: Int = {
var result: Int = 0
for i in 0...9 {
if tableWithBooleans[i] {
result += 1
}
}
return result
}()

Units and Measurements in Swift

I am trying to make a measurement entry keyboard class that has a text field for the value, and a picker for the unit.
I am having trouble using the Measurement type because of its generic behaviour.
I would like my class to return a new Measurement instance based on the initial value, but allowing the user to change the unit without necessarily converting it. I get the error "Cannot convert value of type 'Unit' to expected argument type 'T'" on the line where I am initialising meas with a value, and a unit of a different type.
Also, is there an way to iterate through the built-in sub units of a Dimension Type? i.e get all the sub units of UnitPressure for example.
If someone could just point me to an answer about similar generic behaviour, that would be much appreciated.
class MeasurementPicker<T : Dimension> {
init(initialUnit: Measurement<T>) {
self.initUnit = initialUnit
}
var initUnit: Measurement<T>
func getUnitList() -> [Unit]? {
switch initUnit.unit.self {
case is UnitPressure:
let retUnits: [Unit]? = [
UnitPressure.bars,
UnitPressure.gigapascals,
UnitPressure.hectopascals,
UnitPressure.inchesOfMercury,
UnitPressure.kilopascals,
UnitPressure.megapascals,
UnitPressure.millibars,
UnitPressure.millimetersOfMercury,
UnitPressure.newtonsPerMetersSquared,
UnitPressure.poundsForcePerSquareInch
]
return retUnits
default:
return nil
}
}
func getNewType(index: Int) -> Measurement<T> {
let myNewUnit : Unit = getUnitList()![index]
var meas = Measurement<T>.init(value: 6, unit: myNewUnit)
}
}
let x = Measurement(value: 5.5, unit: UnitPressure.kilopascals)
let y = MeasurementPicker<UnitPressure>(initialUnit: x)
let z = y.getNewType(index: 0)
print(z.unit.symbol)
There is no need to create a generic class. Just create a unit or dimension property. And in your method getNewType return Measurement<Unit> or just the unit or the dimension. You can also just use a subscript to get the dimension from your list:
class MeasurementPicker {
init(dimension: Dimension) { self.dimension = dimension }
var dimension: Dimension
var list: [Dimension] {
switch dimension.self {
case is UnitPressure:
return [UnitPressure.bars,
UnitPressure.gigapascals,
UnitPressure.hectopascals,
UnitPressure.inchesOfMercury,
UnitPressure.kilopascals,
UnitPressure.megapascals,
UnitPressure.millibars,
UnitPressure.millimetersOfMercury,
UnitPressure.newtonsPerMetersSquared,
UnitPressure.poundsForcePerSquareInch]
default: return []
}
}
}
Usage:
let y = MeasurementPicker(dimension: UnitPressure.kilopascals)
let z = y.list[0]
print(z.symbol) // "bar\n"

Writing a Swift function that returns itself

I have this piece of code in Python :
def f(x, y):
# do something...
return f
I'm trying to write this in Swift but can't figure out if it's possible or not. The return type would get infinitely long.
Here's a part of the game I'm trying to recreate written in Python. It's a dice game with multiple commentary functions that get invoked on each round. After every round finishes, the commentary function could return itself but with some changes as well (such as changing variables in the enclosing scope).:
def say_scores(score0, score1):
"""A commentary function that announces the score for each player."""
print("Player 0 now has", score0, "and Player 1 now has", score1)
return say_scores
def announce_lead_changes(previous_leader=None):
"""Return a commentary function that announces lead changes."""
def say(score0, score1):
if score0 > score1:
leader = 0
elif score1 > score0:
leader = 1
else:
leader = None
if leader != None and leader != previous_leader:
print('Player', leader, 'takes the lead by', abs(score0 - score1))
return announce_lead_changes(leader)
return say
def both(f, g):
"""Return a commentary function that says what f says, then what g says."""
def say(score0, score1):
return both(f(score0, score1), g(score0, score1))
return say
def announce_highest(who, previous_high=0, previous_score=0):
"""Return a commentary function that announces when WHO's score
increases by more than ever before in the game.
assert who == 0 or who == 1, 'The who argument should indicate a player.'"""
# BEGIN PROBLEM 7
"*** YOUR CODE HERE ***"
def say(score0,score1):
scores = [score0,score1]
score_diff = scores[who]-previous_score
if score_diff > previous_high:
print(score_diff,"point(s)! That's the biggest gain yet for Player",who)
return announce_highest(who,score_diff,scores[who])
return announce_highest(who,previous_high,scores[who])
return say
# END PROBLEM 7
The play function that repeats until some player reaches some score:
def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided,
goal=GOAL_SCORE, say=silence):
"""Simulate a game and return the final scores of both players, with Player
0's score first, and Player 1's score second.
A strategy is a function that takes two total scores as arguments (the
current player's score, and the opponent's score), and returns a number of
dice that the current player will roll this turn.
strategy0: The strategy function for Player 0, who plays first.
strategy1: The strategy function for Player 1, who plays second.
score0: Starting score for Player 0
score1: Starting score for Player 1
dice: A function of zero arguments that simulates a dice roll.
goal: The game ends and someone wins when this score is reached.
say: The commentary function to call at the end of the first turn.
"""
player = 0 # Which player is about to take a turn, 0 (first) or 1 (second)
# BEGIN PROBLEM 5
"*** YOUR CODE HERE ***"
scores = [score0,score1]
strategies = [strategy0,strategy1]
while score0 < goal and score1 < goal:
scores[player] += take_turn(strategies[player](scores[player], scores[other(player)]),
scores[other(player)], dice)
swap = is_swap(scores[player], scores[other(player)])
player = other(player)
if swap:
scores[0],scores[1] = scores[1], scores[0]
score0,score1 = scores[0],scores[1]
# END PROBLEM 5
# BEGIN PROBLEM 6
"*** YOUR CODE HERE ***"
say = say(score0,score1)
# END PROBLEM 6
return score0, score1
Let's try to write such a thing.
func f() {
return f
}
Now the compiler complains because f is not declared to return anything when it does return something.
Okay, let's try to add a return value type i.e. A closure that accepts no parameters and return nothing.
func f() -> (() -> ()) {
return f
}
Now the compiler complains that f is () -> (() -> ()), and so cannot be converted to () -> ().
We should edit the declaration to return a () -> (() -> ()), right?
func f() -> (() -> (() -> ())) {
return f
}
Now f becomes a () -> (() -> (() -> ())), which cannot be converted to a () -> (() -> ())!
See the pattern now? This will continue forever.
Therefore, you can only do this in a type-unsafe way, returning Any:
func f() -> Any { return f }
Usage:
func f() -> Any {
print("Hello")
return f
}
(f() as! (() -> Any))()
The reason why this is possible in python is exactly because Python is weakly typed and you don't need to specify the return type.
Note that I do not encourage you to write this kind of code in Swift. When you code in Swift, try to solve the problem with a Swift mindset. In other words, you should think of another way of solving the problem that does not involve a function like this.
Not exactly what you want perhaps but you can do something similar with a closure
typealias Closure = (Int) -> Int
func doStuff(action: #escaping Closure, value: Int) -> Closure {
let x = action(value)
//do something
return action
}
Well, actually you can do something like that in Swift, only you will have to separate the linear part of code from the recursive, and wrap recursive code in the struct:
// Recursive code goes here:
struct Rec<T> {
let call: (T) -> Rec<T> // when code `from outside` calls it, it will execute linear part and return recursive
init(closure: #escaping (T) -> Void) { // create new loop with linear `closure`
self.call = {
closure($0) // execute linear code
return Rec(closure: closure) // return recursive wrapper
}
}
subscript(input: T) -> Rec<T> { // this exist just to simulate `f(x)` calls, using square brackets notation
return self.call(input)
}
}
// Linear code goes here
let sayScores = Rec { (score0: Int, score1: Int) in
print("Player 0 now has", score0, "and Player 1 now has", score1)
}
Usage:
let temp = sayScores.call((1, 2)) // will print: Player 0 now has 1 and Player 1 now has 2
temp[(0, 0)][(10, 42)] // temp is `Rec<(Int, Int)>`
// will print:
// Player 0 now has 0 and Player 1 now has 0
// Player 0 now has 10 and Player 1 now has 42
So you may make it work, but I don't know whether you should use it in Swift.

Setting an immutable variable with conditional logic in Swift

I have a super simple question on the best way (i.e. style) to do this correctly in Swift.
if a > b {
let x = 1
} else {
let x = 2
}
//then procede to use x
Obviously, this will not work, because the scope of x is only within each branch of the if. But what is the preferred way to go about this, if I want x to be immutable? So far, I have been doing this:
var x:Int
if a > b {
x = 1
} else {
x = 2
}
//then procede to use x
which works, but leaves x as mutable. The next choice is to use the ternary operator as in:
let x = a > b ? 1 : 2
This leaves x immutable but leaves a bit to be desired in terms of readability when the conditions and resulting values become complex. Also, using the ternary solution completely falls down with a more complex example:
if a > b {
let x = 1
} else if b > c {
let x = 2
} else {
let x = 3
}
}
//procede to use x
or this:
switch a {
case 1:
let x = 1
case 2:
let x = 2
default:
let x = 3
}
//procede to use x
Is their any way to promote the scope of a let outward one level, or some other way this type of situation is normally handled?
You can use let in your 2nd example:
let x:Int
if a > b {
x = 1
} else {
x = 2
}
As long as x is fully initialized in all paths, this works.
It works with the switch as well:
let a = 3
let x: Int
switch a {
case 1:
x = 1
case 2:
x = 2
default:
x = 3
}
you can also achieve it using class.
like this
class immutableVariable{
private var value: Any
init(newValue: Any = "") {
self.value = newValue
}
func changeValue(withNewValue newValue: Any){
self.value = newValue
}
func getValue() -> Any{
return value
}
}
and then call it like
let x = immutableVariable()
if a > b{
x.changeValue(withNewValue: 1)
}else{
x.changeValue(withNewValue: 2)
}
and access values using
print(x.getValue())

Using a Closure as a While Loop's Condition

I want to use a closure as a condition for a while loop. This is what I have:
var x: Int = 0
var closure = {() -> Bool in return x > 10}
while closure {
x += 1
println(x) // never prints
}
It never prints anything. If I change it to closure(), it doesn't work either.
Any help would be appreciated.
There are two problems here.
Firstly, as written, your code won't even compile. You need to change while closure to while closure().
Second, the bigger problem, your closure logic is wrong. x > 10 never returns true because x is never greater than 10. Flip the sign over and it'll work.
Swift 2
var x = 0
var closure = { () -> Bool in return x < 10 }
while closure() {
++x
print(x)
}
Swift 1.2
var x = 0
var closure = { () -> Bool in return x < 10 }
while closure() {
++x
println(x)
}
Two issues:
Your logic is backwards. You want to print while x is less than 10, so:
when you call a closure directly you do so as you would a function, i.e. with parenthesis.
Updated code, tested with Swift 2.0:
var x: Int = 0
var closure = {() -> Bool in return x < 10}
while closure() {
x += 1
print(x)
}
You need to call the closure with (), and your condition is the wrong way around so that it's false at the beginning (it should be x < 10, not x > 10). Change to:
var x = 0
var closure: () -> Bool = { x < 10 }
while closure() {
++x
print(x)
}
Take advantage of abbreviation opportunities to make your code more concise and elegant.
var x = 0
let closure = { x < 10 }
while closure() {
x++
}
x // 10