I run a book reading server on discord, where we decided to read the book SICP (Structure and Interpretation of Computer Programs). The idea was to get better at programming in general and get a first hands-on with FP. So, as a pre-cursor to this book reading, I tried to explain FP, as we wanted to get some hands-on getting used to a LISP style FP, before reading the book. And few folks in the server struggled with very basic questions. • What is state? • Why do we model problems as state? • What does it mean when people say “in FP, state belongs to the function”? I think, there must be some beginners in this channel facing the same issue, so I cooked up a small ELI5 Style example to explain the "Idea of State and State Machines". I took a simple example of "Tic-Tac-Toe", and went from state-machine to code. https://github.com/harsh098/eli5-state-machines/blob/main/README.md I used Python deliberately, as, most beginners come from imperative/OO backgrounds, and Python lets me demonstrate FP principles without overwhelming the reader. The full FP implementation is intentionally left out as an exercise. > After you end up reading this, it is important that you write an equivalent Clojure Implementation using the same approach, without looking at the Python code, just a state machine and the same thinking process. This is very important. Any improvement and suggestions are welcome, I will add a clojure solution later. It took me a lot of time to come up with a step by step idea for the same. Turns out, I had to revisit a lot of concepts to explain even a lot of fundamental stuff.
Well, there isn't any one true way... You do you! Write the explanation you wish someone had given you when you were struggling with that topic (state machines, for example).
ICYMI: Rafal Dittwald gave a wonderful talk / demo at Clojure North about the same subject (not state machines per se, but going from imperative/OO -> fp way, in a Javascript program). Solving Problems the Clojure Way - Rafal Dittwald https://www.youtube.com/watch?v=vK1DazRK_a0
@adityaathalye This one was a wonderful talk. Thanks for sharing.
Awesome! > • What is state? Huh. I don't think I would be able to quickly and accurately answer that.
@p-himik did some updates to fix some errors in the README.md please refresh if you're reading.
right now
This is a nice project idea, but I think the choice of tic-tac-toe isn't serving you well. The actual state of a game of tic-tac-toe is just the board. Things like if the game is over or not, or whose turn it is, can be derived from the board state (if there are an odd number of empty squares, it is 'x's turn, for example). In my experience, the wins of functional programming come from simplifying the data (state) as much as possible, and then implementing everything as separate functions of that data. Storing derived data in the state itself is a recipe for things eventually getting out of sync and into invalid or confusing states.
I was going to go to the squint playground to implement my ideas, but this was already there (!) ha!, and it's close enough: https://squint-cljs.github.io/squint/?src=https://gist.githubusercontent.com/borkdude/6463b9628292e820742838b840096386/raw/8602b9153010af1a11c775dadebbedeae32c8e08/tictactoe.cljs
@borkdude ftw. 🙇
Though, even there, the current player is reified into the state, ... however, the code is well factored, and get-player could be fixed to not need it, and then the every instance of :player and other-player could just be deleted. simple_smile
I'd probably also re-factor the predicates there into a single board classification function that would, in a single call, tell if the game were still going on, and if not who won or if it were a draw.
I think oxo is useful because it is a small state problem. Everybody already knows most board states (or at least the winning ones), so the instructor can move away from problem definition, and do lots of variations of playing with state <v/s> fp-transformation. Because, grokking brand-new programming concepts requires a person to try solving the same thing multiple different ways. Here's tictactoe in some FP-style Bash, and it speaks to you with computer voice :) https://github.com/adityaathalye/oxo ... here, the board is its own state :D
__player_move_available() {
fit_board_to_square_grid | grep '-' > /dev/null
}
__player_wins_grid_row() {
local player_win_func=${1}
fit_board_to_square_grid | $player_win_func
}
_player_wins_grid_col() {
local player_win_func=${1}
fit_board_to_square_grid | transpose_board | $player_win_func
}Harsh, how much stuff do you think you can remove from the explanation? There's a lot going on there. What is the smallest possible explanation built with the smallest possible series of pedagogical steps?
e.g. Why introduce state machines as a concept at all? Can the illustration simply be two compare-and-contrast programs --- the traditional Class-y way, and the alternate pure-fp-way? Then ask questions --- what are the drawbacks of the "classy" way (in python)? -> concurrent modification of state what are the drawbacks of the "fp" way (in python)? -> the footgun of call by reference v/s call by value (you need to deep-clone shit all the time) This is already the crux of it. No need for state machines.
@adityaathalye I think, I can add about the compare-and-contrast programs --- OO vs FP approach. I intentionally left that as an exercise to the reader. In my case, I wanted to introduce the idea of state and how to model problems using this idea. A lot of explanations of arriving at the number of states could be removed, but my audience was "People who know a thing or two about programming, and do not come from CS background". For them I wanted to show the thought process, of how I arrived at the states, and, not introducing state machines would do injustice to the overall idea, and would again leave the state as an abstract idea for them, which I did not want.
I wanted to encourage them to read some literature around it too. So that, If they end up seeing a state machine in docs of a project or while reading a technical book/whitepaper, they don't get overwhelmed. (I see them so many times). But let me know if there's a better way I can accomplish this.