dbgrandi / drunken-octo-bear

Functional Swift exercises for real world development
MIT License
5 stars 0 forks source link

Chapters 1 & 2 #2

Open orta opened 9 years ago

orta commented 9 years ago

C1 : Introduction

Given that there's no code in here, there's no exercises. It's interesting from the perspective of how do you pitch Functional Programming without being autological. Instead of trying to give a formal mathematical approach to functional programming they opted to highlight the qualities it embodies, notably:

This chapter aims to showcase building some imperitve code, and then starts to turn it into function components. They build up a single function inRange for determining whether a battleship's can shoot something in range (will I hit myself, is it too far, etc).

The first thing they do is define a typealias for the type of function they want: typealias Region = Position -> Bool. This means syntactically that whenever they think of a region they're really talking about:

Instead of defining an object of struct to represent regions, we represent a region by a function that determines if a given point is in the region or not. If you're not used to functional programming, this may seem strange.

They're right. It does. They then go into the reasoning for it, and for the name..

These names suggest that they denote a function type, yet the key philosophy underlying functional programming is that functions are values, no different from structs, integers or booleans. Using a separate naming convention for functions would violate this philosophy.

They then start splitting the original method up by giving examples of functions that conform to Region

function What it takes What it returns
circle (radius) Takes a radius A function that returns if the point passed to said function is inside a circle of that radius.

They then explore improving the circle method to add a position for the circle, but backtrack on it. Explaining that a more functional approach would be to write a generic region transformer.

function What it takes What it returns
shift (offset, region) Takes an offest and a Region function It makes a new Postition by offsetting the original by x and y, then returns the region function with the new Position.

This is one of the core concepts of functional programming: rather than creating increasingly complicated functions such as circle two, we have written a function shift which modifies another function.

They then finish up the rest of the functions required to have a functional version of inRange.

function What it takes What it returns
invert (region) Takes a Region function A function that calls the region function then does a ! on it to swich the return value.
intersection (region, region2) Takes 2 Region functions A function that &&s the two region functions.
union (region, region2) Takes 2 Region functions A function that ||s the two region functions.
difference (region, region2) Takes 2 Region functions A function that intersectionss the first plus the invert of the 2nd region function.

Instead of writing complex functions to solve a specific progrlem we can now use many small functions that can be assembled to solve a wide variety of problems.

They then discuss the upsides / downsides of this approach. One of the oddities here, and I struggled to explain this verbally is that as a region is a function, there is no way to specifically look at what the function is. There is no state that says "square" just a function like square(length) that you would have to run many times ( they mention to visualise you would have to generate a bitmap of whther Positions hit it or not. ) This was a problem that I found with Reactive Cocoa a lot.

They finish up by talking about how spending time upfront thinking about your types will guides your development process the most here.


So I found my run through of this chapter a pretty solid intro. I'm glad they included the point that the example was inspired by a haskell example, didn't like the militery-ness of it. By writing out the tables above I started to really feel like I had a grip on the idea that everything really is returning a function, but that each function we were creating was modifying another one slightly.

dbgrandi commented 9 years ago

C1:Introduction

I've struggled to find an appropriate mental model to help me relate to functional programming.

I grew up using Unix, and have seen people write some pretty powerful programs by stringing together simple commands. Turns out this may be a decent (??) comparison. Composing small commands together with pipes lets you create powerful programs in an ad hoc manner. I read a book years ago (The Unix Philosophy, by Mike Gancarz) that lists some of the principles that were fundamental to the success of Unix. Of the listed tenets, "Make each program do one thing well" and "Make every program a filter" end up promoting functional ideals. In the case of command line apps in Unix, the universal type that everybody agreed on was stdin and stdout.

dbgrandi commented 9 years ago

C2: Thinking Functionally

Orta already did a great job of summarizing what they did in this chapter, so I'll just focus on the parts that stood out from my perspective.

I love the use of typealias to clarify the meaning of code. This is something (well, typedef for most of us still) I should probably apply more to my day to day code. In Cocoa, when I see something as simple as an NSTimeInterval, it's makes it just a bit easier for my brain to understand I'm dealing with time instead of just a double, even though I can treat it as a double.

The definition of Region as a function that takes a Position and returns a Bool was hard for me to read. Thinking of a noun as something that in this case behaves like a verb is something that will just take time for me to be able to read without my brain pausing to translate this in my head. They make an effort to explain this, which makes me feel alright about it being troubling for me. The take away here is that this will seem weird to a lot of programmers because of how most of our coding has reinforced how we internalize that data are nouns and functions are verbs. Turns out that they don't necessarily need to be two separate types of things.

At the end of the chapter they look back at what was created...

The solution is simple and elegant. It is quite different from what you might write, had you just refactored the inRange4 function into separate methods.

I found myself thinking about how I would have gone about refactoring the initial problem and came to the conclusion that I probably would not have ended up where the authors did. They definitely created a simple and elegant solution.

When reading code that other people write, there are two things I always want to get to.

The first is the actual nuts and bolts of how the code works. For most code, this is usually just a matter of reading through and making sure I understand anything non-obvious (e.g. cases where somebody is trying to be clever or tricky).

The second part, and often more important, is understanding why something was written the way it was. If you can understand the mental model that the author had, it gives you a much better ability to understand the tradeoffs that they would have made along the way and why the result looks like it does. In the OOP world, this is usually a case of trying to understand the physical/real-world metaphors that the author used (flaws and all in some cases). I don't think I have the proper notion yet of what this will look like in the functional world, but they give a good hint about it in the next sentence...

The crucial design decision we made was how to define regions. Once we chose the Region type, all the other definitions followed naturally. The moral of the example is choose your types carefully. More than anything else, types guide the development process.

What they are telling us here is a window into how they think about approaching problems. I'm not sure if they emphasise this because it relates specifically to how they approach functional programming or if they emphasize it because it is a core tenet that they follow for all programming. This is something I'll be keeping in mind throughout the rest of the book...thinking about how choosing the initial types would affect the overall approach to solving a problem. That's a muscle I'd like to develop a lot more.