I was sorely tempted to write about ADTs and compare them to people in my life (Trees: the people who go into a discussion with you armed with their version of everything you could possibly say and everything they could possibly say in response and everything you could then reply with and [...] in order to show you up; Stacks: that dude from my spin class who arrives 20min late and leaves 15min early, typifying "Last-In, First-Out" ...) but I think I owe it to myself to write about the toughest subject for me: recursion.
I have alluded jokingly to how confusing I find it, but sadly, this ain't no joke. I struggled endlessly with the MiniMax algorithm in Assignment 2, and I had no idea why I was struggling. I felt like I had the concept down, and more importantly, like I had used the type contracts of the various methods to figure out which method I needed to apply when. (It was kind of a cool little puzzle; realizing "OK, this one yields an instance of State class, this one yields a list but needs a State as its argument... this one yields an instance of Move class...") But somehow I was stumbling and kept getting errors, and actually struggled with the algorithm right up until it was due. I had a hard time figuring out how to store and maximize (or minimize) the results of each recursive state without losing a reference to those results at the next iteration. My housemates must have thought I was solving P vs NP with all the scribbles and diagrams and alternate states I had drawn over our communal chalkboard in the kitchen, but sadly, the problem was incredibly elementary and my scribblings belied my actual lack of genius, rather than the presence of it.

J Musset, Droste, c. 1904. This is an early instance of recursion,
appearing in a cocoa ad in the early 1900s. The figure-of-a-figure
recursive image style is often called the Droste effect.
As far as I can tell, the best clue to how to solve recursion problems if you are stuck is indeed to look at the type contracts. Step away from the computer and on paper, or on a drawing surface or something, build a 'map' for yourself: what you want to use as input, what can happen to it, and then what it can spit out (in a few cases). For example: if you know your output must be a list, or the sum (or max) element of a list, somewhere along the way you will probably be choosing between appending an element or item that you receive, and performing another recursive loop to find that element. Sometimes it's even helpful to stop stressing about your function/method as being recursive, and just imagine you were writing the whole thing. It will immediately become obvious that you are wanting to repeat yourself and certain steps in the pseudocode. That gives a good clue as to where the recursion comes in.
Another stumbling block lies in improper tracing of recursive function calls, which is why it is so important to practice tracing function calls, as we did for weeks leading up to the recursion exercises. I was grateful for these exercises, because it can be daunting to try to figure out what the computer is doing 'behind the scenes,' and because I think it makes you a better programmer to have to write some things out manually and get a sense of them. Often, when you're struggling with a recursive function/method (or really, with any function/method), it's because you don't actually understand what it is doing, and it is generally doing something that you don't expect. A poor man's version of tracing (a.k.a my version) involved lots of breakpoints and lots of print() statements. However, prof. Heap introduced me to the world of assert: statements, which has drastically improved my debugging skills and also looks way less awkward. (in particular, printing repr() of an object all the time is not an ideal debugging technique.)
These techniques were particularly useful for me in getting to know the starter code that was provided for us, which is great since reading other people's code (as I mentioned in a previous post) is not something I considered my strength. Again, it was super fun, kind of like a puzzle, and very easy to follow after a certain point. I have tried to do the same with snippets on stackexchange etc., but I find them pretty tough to follow. So it was a bit of a boost to find out that I am, in fact, capable of it, I just need to practice. (It's amazing
how easy it is to forget that.)