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.
Related
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)
}
...or how can I use the index inside the for loop condition
Hey people
Since we're left with no c style for loops in swift 3 I can't seem to find a way to express a bit more complex for loops so maybe you can help me out.
If I were to write this
for(int i=5; num/i > 0; i*=5)
in swift 3 how would I do that?
The closes I came by was:
for i in stride(from: 5, through: num, by: 5) where num/i > 0
but this will of course iterate 5 chunks at a time instead if i being: 5, 25, 125 etc.
Any ideas?
Thanks
Using a helper function (originally defined at Converting a C-style for loop that uses division for the step to Swift 3)
public func sequence<T>(first: T, while condition: #escaping (T)-> Bool, next: #escaping (T) -> T) -> UnfoldSequence<T, T> {
let nextState = { (state: inout T) -> T? in
// Return `nil` if condition is no longer satisfied:
guard condition(state) else { return nil }
// Update current value _after_ returning from this call:
defer { state = next(state) }
// Return current value:
return state
}
return sequence(state: first, next: nextState)
}
you can write the loop as
let num = 1000
for i in sequence(first: 5, while: { num/$0 > 0 }, next: { $0 * 5 }) {
print(i)
}
A simpler solution would be a while-loop:
var i = 5
while num/i > 0 {
print(i)
i *= 5
}
but the advantage of the first solution is that the scope of the loop variable is limited to the loop body, and that the loop variable is a constant.
Swift 3.1 will provide a prefix(while:) method for sequences,
and then the helper function is no longer necessary:
let num = 1000
for i in sequence(first: 5, next: { $0 * 5 }).prefix(while: { num/$0 > 0 }) {
print(i)
}
All of above solutions are "equivalent" to the given C loop.
However, they all can crash if num is close to Int.max
and $0 * 5 overflows. If that is an issue then you have to check
if $0 * 5 fits in the integer range before doing the multiplication.
Actually that makes the loop simpler – at least if we assume that
num >= 5 so that the loop is executed at least once:
for i in sequence(first: 5, next: { $0 <= num/5 ? $0 * 5 : nil }) {
print(i)
}
For completeness: an alternative to the while loop approach is using an AnyIterator:
let num = 1000
var i = 5
for i in AnyIterator<Int>({
return i <= num ? { defer { i *= 5 }; return i }() : nil
}) {
// note that we choose to shadow the external i variable name,
// such that any access to i within this loop will only refer
// to the loop local immutable variable i.
print(i)
// e.g. i += 1 not legal, i refers to a constant here!
} /* 5
25
125
625 */
This method suffers from the same drawback as the while loop in that the loop "external" i variable persists outside and after the scope of the loop block. This external i variable is not, however, the i variable that is accessible within the loop body, as we let the loop body variable i shadow the external one, limiting access to i within the body to the immutable, temporary (loop scope local) one.
...or how can I use the index inside the for loop condition
Hey people
Since we're left with no c style for loops in swift 3 I can't seem to find a way to express a bit more complex for loops so maybe you can help me out.
If I were to write this
for(int i=5; num/i > 0; i*=5)
in swift 3 how would I do that?
The closes I came by was:
for i in stride(from: 5, through: num, by: 5) where num/i > 0
but this will of course iterate 5 chunks at a time instead if i being: 5, 25, 125 etc.
Any ideas?
Thanks
Using a helper function (originally defined at Converting a C-style for loop that uses division for the step to Swift 3)
public func sequence<T>(first: T, while condition: #escaping (T)-> Bool, next: #escaping (T) -> T) -> UnfoldSequence<T, T> {
let nextState = { (state: inout T) -> T? in
// Return `nil` if condition is no longer satisfied:
guard condition(state) else { return nil }
// Update current value _after_ returning from this call:
defer { state = next(state) }
// Return current value:
return state
}
return sequence(state: first, next: nextState)
}
you can write the loop as
let num = 1000
for i in sequence(first: 5, while: { num/$0 > 0 }, next: { $0 * 5 }) {
print(i)
}
A simpler solution would be a while-loop:
var i = 5
while num/i > 0 {
print(i)
i *= 5
}
but the advantage of the first solution is that the scope of the loop variable is limited to the loop body, and that the loop variable is a constant.
Swift 3.1 will provide a prefix(while:) method for sequences,
and then the helper function is no longer necessary:
let num = 1000
for i in sequence(first: 5, next: { $0 * 5 }).prefix(while: { num/$0 > 0 }) {
print(i)
}
All of above solutions are "equivalent" to the given C loop.
However, they all can crash if num is close to Int.max
and $0 * 5 overflows. If that is an issue then you have to check
if $0 * 5 fits in the integer range before doing the multiplication.
Actually that makes the loop simpler – at least if we assume that
num >= 5 so that the loop is executed at least once:
for i in sequence(first: 5, next: { $0 <= num/5 ? $0 * 5 : nil }) {
print(i)
}
For completeness: an alternative to the while loop approach is using an AnyIterator:
let num = 1000
var i = 5
for i in AnyIterator<Int>({
return i <= num ? { defer { i *= 5 }; return i }() : nil
}) {
// note that we choose to shadow the external i variable name,
// such that any access to i within this loop will only refer
// to the loop local immutable variable i.
print(i)
// e.g. i += 1 not legal, i refers to a constant here!
} /* 5
25
125
625 */
This method suffers from the same drawback as the while loop in that the loop "external" i variable persists outside and after the scope of the loop block. This external i variable is not, however, the i variable that is accessible within the loop body, as we let the loop body variable i shadow the external one, limiting access to i within the body to the immutable, temporary (loop scope local) one.
...or how can I use the index inside the for loop condition
Hey people
Since we're left with no c style for loops in swift 3 I can't seem to find a way to express a bit more complex for loops so maybe you can help me out.
If I were to write this
for(int i=5; num/i > 0; i*=5)
in swift 3 how would I do that?
The closes I came by was:
for i in stride(from: 5, through: num, by: 5) where num/i > 0
but this will of course iterate 5 chunks at a time instead if i being: 5, 25, 125 etc.
Any ideas?
Thanks
Using a helper function (originally defined at Converting a C-style for loop that uses division for the step to Swift 3)
public func sequence<T>(first: T, while condition: #escaping (T)-> Bool, next: #escaping (T) -> T) -> UnfoldSequence<T, T> {
let nextState = { (state: inout T) -> T? in
// Return `nil` if condition is no longer satisfied:
guard condition(state) else { return nil }
// Update current value _after_ returning from this call:
defer { state = next(state) }
// Return current value:
return state
}
return sequence(state: first, next: nextState)
}
you can write the loop as
let num = 1000
for i in sequence(first: 5, while: { num/$0 > 0 }, next: { $0 * 5 }) {
print(i)
}
A simpler solution would be a while-loop:
var i = 5
while num/i > 0 {
print(i)
i *= 5
}
but the advantage of the first solution is that the scope of the loop variable is limited to the loop body, and that the loop variable is a constant.
Swift 3.1 will provide a prefix(while:) method for sequences,
and then the helper function is no longer necessary:
let num = 1000
for i in sequence(first: 5, next: { $0 * 5 }).prefix(while: { num/$0 > 0 }) {
print(i)
}
All of above solutions are "equivalent" to the given C loop.
However, they all can crash if num is close to Int.max
and $0 * 5 overflows. If that is an issue then you have to check
if $0 * 5 fits in the integer range before doing the multiplication.
Actually that makes the loop simpler – at least if we assume that
num >= 5 so that the loop is executed at least once:
for i in sequence(first: 5, next: { $0 <= num/5 ? $0 * 5 : nil }) {
print(i)
}
For completeness: an alternative to the while loop approach is using an AnyIterator:
let num = 1000
var i = 5
for i in AnyIterator<Int>({
return i <= num ? { defer { i *= 5 }; return i }() : nil
}) {
// note that we choose to shadow the external i variable name,
// such that any access to i within this loop will only refer
// to the loop local immutable variable i.
print(i)
// e.g. i += 1 not legal, i refers to a constant here!
} /* 5
25
125
625 */
This method suffers from the same drawback as the while loop in that the loop "external" i variable persists outside and after the scope of the loop block. This external i variable is not, however, the i variable that is accessible within the loop body, as we let the loop body variable i shadow the external one, limiting access to i within the body to the immutable, temporary (loop scope local) one.
I've been trying to convert this block of code from Objective-C (taken from https://gist.github.com/mikeash/1254684) to Swift. I've used it successfully to repeat a block of code based on results from API calls. Is there a better method to do this in Swift?
dispatch_block_t recursiveBlockVehicle(void (^block)(dispatch_block_t recurse)) {
return ^{
block(recursiveBlockVehicle(block));
};
}
Any help is appreciated.
Here’s a straight translation of your obj-c version:
func recursiveBlockVehicle(block: #escaping (()->Void)->Void) -> ()->Void {
return { block(recursiveBlockVehicle(block: block)) }
}
// test usage
var i = 5
let block = recursiveBlockVehicle { recurse in
if i > 0 {
print("\(i--) ")
recurse()
}
else {
println("blastoff!")
}
}
block() // prints 5 4 3 2 1 blastoff!
(I’ve subbed out the dispatch_block_t since it doesn’t feel necessary in the Swift version, but you can use it instead of ()->Void instead if you prefer)
For the 1-parameter version, you can use generics rather than the obj-c id approach, so it can create type-safe single-parameter recursive blocks:
func recursiveBlockVehicle<T>(block: #escaping (T, (T)->Void)->Void) -> (T)->Void {
return { param in block(param, recursiveBlockVehicle(block: block)) }
}
let block1: (Int)->Void = recursiveBlockVehicle { i, recurse in
if i > 0 {
print("\(i) ")
recurse(i-1)
}
else {
print("blastoff!")
}
}
block1(5) // prints 5 4 3 2 1 blastoff!
(and Swift overloading means you don’t have to give them different names)
...and if you want your recursive function to return a value:
func recursiveBlockVehicle<T,U>(block: #escaping (T, (T)->U)->U) -> (T)->U {
return { (param: T)->U in block(param, recursiveBlockVehicle(block: block)) }
}
let factorial: (Int)->Int = recursiveBlockVehicle { i, factorial in
return i > 1 ? i*factorial(i-1) : 1
}
factorial(4) // returns 24
Note, this last one is really the only one you need – since T and U can be Void, it serves the purposes of the zero-parameter non-returning one too, though you have to write your closures to take two parameters (the first one of which you can ignore, since it’ll be void), i.e.:
let block: ()->() = recursiveBlockVehicle { _, recurse in
If you like this sort of stuff you should check out the 2014 WWDC Advanced Swift video which as an example of a memoizing recursive function caller.