 After player sequence, we then have another function, getMove, which again takes just one argument, the board, and what this getMove function does is it parses the string input that the user enters at the console, makes sure that it is a proper number, and that that number corresponds to an as-of-yet unoccupied slot on the board, and so is a proper move. If the move is proper, getMove will return the slot number which the user entered, otherwise if the input is invalid, getMove will return nil. Looking at the body, first we have a let form to which we are binding a value for the symbol input. Input takes the result of this try form, the body of which uses the Java integer class static method parseInt to parse the string returned by readLine as an integer. ReadLine you may recall from the Rock, Paper, Scissors program is a function which will block the program until the user enters something at the console and hits enter, and then what they've typed, not including that enter character, the newline character, is returned as a string, and this string is then going to get parsed as an int, and if the string passed the parseInt is not a valid integer, it's going to throw an exception, so that's why we have this int a try block. And notice that in our exception handler, in our catch block, that's going to simply return nil, because in the case where the user entered something other than an integer, we want input to be bound the value nil. So in the let form, input will be bound either an integer or the value nil, and in the body of the let, we have this if form where we are testing whether or not the value of input is found in board, and we do this using the sum function. Like the every function, sum takes as its first argument a predicate function, and then some sequence. Every element of the sequence is passed in turn to this predicate function, and the first time this predicate function returns true, the sum function will return with that value of the sequence. If though none of the calls to the predicate function return true, then sum will return nil. So our condition here will be true when the value of input matches any of the elements of board. And when this condition is true, the if form returns input, otherwise it returns nil. And what the if form returns, that's what the let form returns and in turn what the function itself returns. So assuming say that the user enters the number three at the console, and so input is bound the value three, and say that our board doesn't yet have an X or O in slot three. Well then the board vector should have the number three in it. Because again in our starting board, each of the slots is occupied by a number designating the slot. So if slot three isn't occupied, then the if condition will be true, and the if will return three, and so the let form will return three, and hence the function will return three. If however the slot three were already occupied with a keyword X or keyword O, then the condition would test false and we get back nil. Likewise, if say the user entered some non valid slot number like zero or negative five or 23, none of those are proper slot numbers. And so the condition again would also test false and the function would return nil. Okay, we're nearly there. We have two more functions. The next function is take turn, which takes two arguments player and board. And board is a usual format. It's a vector of nine values. But player should be a keyword of either X or O. Because we use those keywords to designate the two players. This take turn function like the get move function is impure. It's dealing with side effects. And first thing it does is prompt the user with the text, select your move player X or O by pressing one to nine and hitting enter. Note that print line takes any number of strings as argument. The second of which is the player name returned by the player name function. So after prompting the user, we then go into a loop where in each iteration we need to move. So we call get move passing in the current state of the board. Because get move might return nil indicating an invalid input, we then in the loop have this test with a condition move. And if move is not nil, we'll have this call to a soak. But otherwise, if move is nil, we execute this do form, which prompts the user with move was invalid, select your move again player, whatever, which then invokes recur with another call to get move. So as long as the user enters invalid input, they're going to get prompted to enter another value, and this loop will continue iterating. If though the move is valid, then this call to a soak will take the current state of the board and at the index, which is one less than move. Because remember these slot names, like say three is actually at index two of the vector. At that index, we want to replace the slot number with the keyword designating the player, the keyword X for player X and the keyword over player O. So that's what this call to a soak does. It returns a modification of the board in which a player has made a move. And so that new vector returned by a soak gets returned by the if and then in turn returned by the loop, which is then in turn returned by the function. So that's what take turn returns is a new state of the board. Finally, the last function of our program is the kickoff function, the function we invoke first play game. In the body, we have this loop for which the first iteration we bind to board the value of starting board and we bind to player sequence the value of the global player sequence. Starting board recall is the vector with nine elements, the numbers 123456789 and player sequence is an infinite sequence that goes keyword X keyword O keyword X keyword O keyword X keyword O and infinitum. In the body of this loop, we have let for which we bind to winner, the result of board passed to the winner question mark function, which recall returns keyword X keyword O or nil if neither player has yet one. And in the body of this let we print line current board and then we use the print board function to actually display the board on the console. And then we have this con form the con form again short for conditions is effectively like an if else ladder. And our first condition here is just the variable winner. And if that is true, if it has the value keyword X or keyword O rather than the value nil, then we're going to print out player so and so wins using the player name function to get the proper string representation of the winner. Because we don't want to display a colon because it looks ugly. If the winner is not true if it's nil, then we move on to the next condition, which is a test of whether the board is full or not. If the board is full, then the game is a draw so we print game as a draw. And then in the default case denoted with the keyword else, we have neither winner and the game is not yet a draw. So we do another iteration. And so one of the players needs to take a turn. So we call first on player sequence to get either keyword X or keyword O and we pass that to take turn with the current state of the board. So either player X or O takes a turn. And because in the next iteration we want it to be the other player's turn, we take the rest of player sequence. If player sequence starts with X, then rest of player sequence should start with O and vice versa. So be clear that in each iteration we are rebinding the board, a new state of the board in which one of the players has taken a turn and rebinding to player sequence the rest of the previous player sequence. And so for each iteration a call to first on player sequence will alternate back and forth between X and O. And so our game will proceed alternating between turns of the two players until either we have a winner or the game is a draw because the board is full. So those are all the functions of our tic-tac-toe game. And last thing all we need to do is just invoke our kickoff function play game. So that's what we have here in the last line.