I'm working on a card game and would like to make a function that will loop through my array of Players
and perform some function for each player, so I do not have tons and tons of
for var player in Players {
player.doSomeFunction()
}
All over my code. Instead, I'd like something like the below:
func everyone(doThis: func) {
for var player in Players {
player.doThis(<params, etc…>)
}
}
So that I can call Players.everyone(doThis(params, etc…))
in other places of the code instead of having to loop through the players each and every time I need to make all players do something.
How do I make a function that takes any function that's defined in a Protocol as its parameter? The trouble I'm having is that it seems that when you use functions as parameters in Swift, you have to define the parameters and return type of the function parameter in the function declaration. Alternately, is there a built-in way to call Players.forAllElements(doThisFunction)
(where Players
is an Array<Player>
)?
In case it helps, I have two Classes that conform to the Player
protocol: ComputerPlayer
and HumanPlayer
.
There seems to be no way to express any-function-in-a-protocol in swift, as to use for a sort of definition of parameter type.
However, with currying and function-types you can do something that may be similar: . You can target all functions with the same signature:
class Player {
var name: String
init(_ name: String) {
self.name = name
}
// Both actions, even if they have different parameter names,
// have the same function signature
func actionOne(foo: String, count:Int) {
print("actionOne:\(name):\(foo):\(count)")
}
func actionTwo(bar: String, amount: Int) {
print("actionTwo:\(name):\(bar):\(amount)")
}
}
let players = [Player("Primero"), Player("Segundo")]
// A function type that receives a Player object, and returns a
// function with the `String, Int` signature
typealias PlayerActionType = (Player) -> (String, Int) -> ()
// This is the function that takes the curried function, and can
// run any function sharing the same signature
func performAction(curriedFunction: PlayerActionType) {
for currentPlayer in players {
let actionFunction = curriedFunction(currentPlayer)
actionFunction("string", 3)
}
}
performAction(Player.actionOne)
performAction(Player.actionTwo)
// Prints:
// actionOne:Primero:string:3
// actionOne:Segundo:string:3
// actionTwo:Primero:string:3
// actionTwo:Segundo:string:3