Friday, December 15, 2017

Learn Functional Programming in Go by Lex Sheehan



Purchase book here.

My publisher just shared the following with me about a week after it was released:
The book ... has been performing good on all our channels and until yesterday we had sold 130 copies. ... It was great news for me and thought of sharing it with you :)  
I deeply appreciate everyone's affirmation (purchase).
I am honored to be a conduit of deep truths of the universe, expressed in diagrams, code examples and prose.
Sincerely,
Lex Sheehan

Thursday, November 30, 2017

Getting Our Go Apps Up & Running on an MS Windows Workstation

The instructions in the book are geared towards a Mac workstation.

This article is written specifically for readers that use an MS Windows workstation.

Install Go

If you don't already have Go installed, install it.  Here's how:

1. Open your web browser and go to https://golang.org/dl/

2. Click the link for go<VER>.windows-amd64.msi
Note: You may need to run the  go<VER>.windows-386.msi binary if you're running a 32bit Windows system.



3. Install Go

Find the setup program that you downloaded and run it (either double click or right-click | Open).
Click <Run> if you're asked if its' okay to run this software.
Click <Yes> if you're asked if it's okay to allow this software to make changes to your computer.

Click <Next>



Leave the default value (C:\Go\) for Go's installation path.

Click <Next>
Click <Next>
Click <Install>
Click <Finish>

Install Cygwin

If you don't already have Cygwin installed, install it.  Here's how:

1. Open your web browser and go to https://cygwin.com/install.html

2. Click the link for setup-x86_64.exe to install
Note: You may need to run the  setup-x86_64.exe binary if you're running a 32bit Windows system.

3. Install Cygwin

Find the setup program that you downloaded and run it (either double click or right-click | Open).
Click <Run> if you're asked if its' okay to run this software.
Click <Yes> if you're asked if it's okay to allow this software to make changes to your computer.

Click <Next>
Choose "Install from Internet"



Leave default value (C:\cygwin) in Root Directory field
Click <Next>
Leave default value in Local Package Directory (Mine is C:\Users\lex\Downloads)
Click <Next>
Click <Next>
Choose a Download Site  (I chose http://mirror.cs.vt.edu)
Click <Next>
If you see a warning about the current ini file, Click <OK>
If it asks to upgrade, Click <OK>
Install git package  (the version for me was 2.15.0-1)

HEY! Did you follow every one of the 4 steps above?  If not, when you try to run the "git clone" command below it will not work.  1) select "Full" view  2) type git in the Search field  3) click where it says "Skip" on the git: Distributed version control system line.  (it should now say something like "2.15.0-1").  4) click <Next>

Click <Next>(You'll see a Progress window)
If you see "In-use file detected" then click <Stop Process> or <Kill Process>
(You may need to click <Stop Process> or <Kill Process> multiple times)
Eventually, you'll see the "Installation Status" window... Click <Finish>

Now, cygwin and git should be installed.  

Note

You can re-run the cygwin setup.exe as many times as you want to add/remove installed packages.

Get source code for book

1. Double click the Cywing Terminal icon on the Windows desktop
2. Enter the following commands to download this book's source files:

cd
mkdir dev
cd dev
git clone https://github.com/l3x/learn-fp-go


Initialize Windows 

cd
cd dev/learn-fp-go/1-functional-fundamentals/ch01-pure-fp/01_oop/
./init-windows.sh

You'll only need to initialize Windows once.  However, every time you start working on a new Go project you'll want to initialize the Go project with it's init script by typing:  . init

Initialize project and run it 

Before you run the ". init" command below, you should edit the init file.  The tenth line of the file looks like this:

#WIN_GOPATH="E:\\\alice\\\dev\\\learn-fp-go\\\1-functional-fundamentals\\\ch01-pure-fp\\\01_oop"

Edit it to look something like this:

WIN_GOPATH="E:\\\YOUR_USERNAME\\\dev\\\learn-fp-go\\\1-functional-fundamentals\\\ch01-pure-fp\\\01_oop"

If you work off your C drive and your username is bob, it might look like this:

WIN_GOPATH="C:\\\bob\\\dev\\\learn-fp-go\\\1-functional-fundamentals\\\ch01-pure-fp\\\01_oop"

For MS Windows users, for every project, you'll need to edit that line to reflect the current directory.

After you have saved the file, run the following:

. init
go-run

It should return this:  Found &{Model:Highlander}

Initializing other projects and running them

To start the second project, cd into its directory and initialize that project.

cd
cd dev/learn-fp-go/1-functional-fundamentals/ch01-pure-fp/02_fib/
. init
go-run


Glide does not work on Windows in Cygwin 

Here's what'll happen when you try to run glide:

Here's another example:


Bottom line:  If you are using MS Windows, you can run the apps that don't have vendor dependencies using Glide.  In other words, the dot glide-update command will not work for MS Windows.  You must find another way to manage your dependencies.  Probably using the standard way will work.  Here's a video that should help you get setup.


Glide Github Issue Created

I created an issue at the glide github repository.  Hopefully, this issue will be fixed by the time you need it.  For details see this issue.

Uninstall Cygwin

Once you're done working through the applications in this book and if you no longer want Go installed on your workstation, here's how to remove Cygwin.

Open a terminal window and enter the following:
takeown /f C:\cygwin /r /d y
icacls c:\cygwin /t /grant everyone:F
del c:\cygwin

Edit files in Cygwin

You can edit files using the vi editor.


Enter vi init to edit the init file.

You can use your arrow keys to navigate down to line 10 and before you get in insert mode, while the cursor is over the # character, hit the x key.  That will delete the #.  Now, you can right-arrow to move to the end of the line and press the x key to delete the 02_fib characters.  Lastly, press the i key to go into insert mode and then type 01_oop.  Press the Escape key an type :wq to save changes.




Saturday, November 18, 2017

Corrections for Learning FP in Go Book

Errors and Corrections

While I did my best to present perfect information, we're all human and make mistakes.  The topics of category theory, functional programming and Go development are extensive and in my effort to organize and condense this information I likely made a few mistakes.  I will post corrections and any other information that might clarify issues in this book here.

If you find any errors and want to share your insights regarding this book feel free to add a comment to this page.  Thanks! Lex

UPDATE:  At the last minute, the Category Theory That Applies chapter 11 was moved to the end of the book.  So, it's best that you read it after immediately after chapter 8 as the author originally intended ;-)  It covers terms like Monoid, Functor, Monad, etc. used in chapters 9 and 10.

Get latest source code here.
If you find any errors, please post a comment on here.


Chapter 1

Words in chapter do not match code

The code is correct.  The words need editing.


Wording in book:


Only the final leaf nodes of are added together to calculate the sum total of 8:

Corrected wording:

Only the final leaf nodes of are added together to calculate the sum total of 5: 


Here's the code:

1-functional-fundamentals/ch01-pure-fp/02_fib/main.go


package main
import (
    "fibonacci")
func main() {
    println(fibonacci.FibSimple(4))
    println(fibonacci.FibMemoized(5))
    println(fibonacci.FibChanneled(6))
}

1-functional-fundamentals/ch01-pure-fp/02_fib/src/fibonacci/meomoize.go 

package fibonacci

type Memoized func(int) int
var fibMem = Memoize(fib)

func Memoize(mf Memoized) Memoized {
   cache := make(map[int]int)
   return func(key int) int {
      if val, found := cache[key]; found {
         return val
      }
      temp := mf(key)
      cache[key] = temp
      return temp
   }
}

func FibMemoized(n int) int {
   return fibMem(n)
}

func fib(x int) int {
   if x == 0 {
      return 0   } else if x <= 2 {
      return 1   } else {
      return fib(x-2) + fib(x-1)
   }
}

Output



URL Missing Dash

This is the correct url: https://github.com/golang/go/wiki/SettingGOPATH

URL for github Repo

The screenshots, links and text reference the repo (this repo) as l3x/fp-go.git, whereas it's actually l3x/learn-fp-go.git.

Error running first example

The screenshot associated to "go run cars.go", shows that one should go run cars.go in the following path: ~/myprojects/fp-go/1-functional-fundamentals/ch01-pure-fp/01_oop.

There is no cars.go in that path, it's actually in ~/myprojects/fp-go/1-functional-fundamentals/ch01-pure-fp/01_oop/src/oop. And even when you do run go run cars.go from that directory, you get:
go run: cannot run non-main package
The easy solution is to use the init script found in every project.  Here's how:
(Double-click image to enlarge)
For details see the How to build and run Go project section in the appendix. 

Many Thanks to Dave for reporting those issues here.

If you're an MS Windows user, you should check this out.

Chapters 1 & 5


Any reference to KISS-Glide  should say Dot Init.  They mean the same thing.  It's the bash initialization script that's explained in detail in the How to build and run Go projects section of the appendix.

Chapter 2

Gleam - distributed MapReduce for Golang

The LuaJit+Go approach has been ditched because of complexity to add new features to Gleam. 

Gleam is now using pure Go everywhere.

Chapter 9


The directions of the arrows are significant 

The g(x) equation should be:  g(x) = x 2 + 1

... rather than not  g(x) = x2 + 1

Chapter 11

Towards the end of the chapter in a section entitled, Fun with Sums, Products, Exponents and Types,  we talked about looking at structures algebraically and finding matching structures.  The image below should look familiar.  It's an updated, slightly improved version of what's in the book:


Appendix

Old content is found in chapter 4.  The new content was moved to the appendix.  It's a conversation that a Java developer a Go developer and an FP developer had regarding error handling in Go.

A Java, Go and FP developer Walk into a Bar...

DeveloperSays...
Java
I do not like the way Go makes me handle errors after every function call.
I want exception handling like this:
try {
   Decrypt()
   Authenticate()
   Charge()
}
catch (Exception e) {
   // handle exception
}
but after adding all those error checks my code looks more like this:
err := Decrypt()
if err != nil {
   return err
}
err = Authenticate()
if err != nil {
   return err
}
Charge()
Go error handling looks like a bunch of scaffolding  obscuring my code's intentions.
GoAs you know, Go does not support exception handling.  Instead, you return errors to inform the calling function/method that something went wrong.  You are supposed to handle an error as soon as possible.  This is what we call the idiomatic way to handle errors.  When you throw exceptions, how far up the call stack will your handler be?  What if your exception gets handled before it reaches your global error handler?  Will it stop or be rethrown?  If rethrown, do you really want to handle your errors more than once?
Go 
Also, since an error is a value we can program it and do.  See that Scan method?  It might encounter an IO error, but it does not immediately return the error.  Instead it returns a boolean value to indicate success.  Later we can check for the error.
scanner := bufio.NewScanner(input)
for scanner.Scan() {
   token := scanner.Text()
   // process token
}
if err := scanner.Err(); err != nil {
   // process the error
}
We can also clean up the following repetitive error checking code:
_, err = fd.Write(p0[a:b])
if err != nil {
   return err
}
_, err = fd.Write(p1[c:d])
if err != nil {
   return err
}
_, err = fd.Write(p2[e:f])
if err != nil {
   return err
}
// and so on
... by writing a helper that will allow us to wait until we're done writing to handle the error. 
var err error
write := func(buf []byte) {
    if err != nil {
        return
    }
    _, err = w.Write(buf)
}
write(p0[a:b])
write(p1[c:d])
write(p2[e:f])
// and so on
if err != nil {
    return err
}

JavaThat is much better, but is that a reusable pattern?  In each of those two examples above, we had to write custom error handling code in two different places, right?  Isn't there a more generic, yet Go idiomatic way to handle errors that will eliminate that repetitive error checking code and allow me to check for errors in one place, at the end of my workflow?
FP
Yes, Java developer there is and it's called the Lexical Workflow Solution.  Read all about it in chapter 11.  If you use it, your code will look something like this:
step = Next(step, Decrypt)
step = Next(step, Authenticate)
step = Next(step, Charge)
json, err := step(nil)
if err != nil {
   // handle error
}
The Go developer's error handling code samples above came from https://blog.golang.org/errors-are-values



Monday, November 13, 2017

The Final Lap

UPDATE:  The publisher changed the book colors to ORANGE & BLUE for us!





Just got this message from my editor:

"We are all set for the final lap. Here we have all the chapters almost in the final form to go in the book."


It's been a marathon.

Cheers!
Lex


Friday, November 10, 2017

Learning Functional Programming in Go - Preface

Until recently the message has been, "Go and Functional Programming.  Don't it."

Functional Programming (FP) is a perfect fit for multi-core, parallel processing.  Go is a concurrency baller (with Goroutines, channels, etc.) and already runs on every available CPU core.

FP reduces complexity.  Simplicity is one on Go’s biggest strengths.

FP scales.  Go scales and we already covered this.  Go away.

So, what can FP bring to Go that will actually improve our software applications?
  • Composition.  FP shows us how to decompose our apps and rebuild them by reusing small building blocks.
  • Monads. Using monads, we are able to safely order our workflows into pipelines of data transformations.
  • Error handling. We can leverage monadic error handling and still maintain compatibility with idiomatic Go code.
  • Performance.  Referential transparency is where we can evaluate our function once and subsequently refer to its pre-computed value.
  • Expressive code.  FP allows us to concisely express business intent in our code. We declare what our functions do, without the clutter of error checking after every function call and without having to follow state changes (pure FP means immutable variables).
  • Simpler code. No shared data means not having to deal with semaphores, locks, race conditions  or deadlocks.
Most people have difficulty grasping functional programming.

I did, too.  When I “got it” I wrote this book.  Take this journey with me.  You’ll see hundreds of illustrations, read easy-to-understand explanations and implement FP in Go code along the way.

I enjoyed coaching soccer. The litmus test I used to determine whether I succeeded as a coach was the answer to this simple question, "Did they all register for next season and request for me to be their coach?"  Just like planning practice, I planned each chapter; Starting with simple concepts and adding to them.  Read this book.  Then you, too, will be able to say, “I got it.”

If you want to improve your FP skills this book is for you.


Coach Lex

Thursday, November 9, 2017

Who this book is for

This book should appeal to two groups:

This book should appeal to two groups:


NON-Programmers:  (Focus on the 110+ page Category Theory chapter.) If you are a…

 • K-12 math teacher and want to see why what you are teaching matters or

 • Math teacher and want to see how what you are teaching relates to other branches of mathematics or

 • Student in law school and want to understand what you will be doing when you plead your client’s case or

 • Soccer enthusiast and like math or

 • Person interested in learning Category Theory or

 • Lover of The Lambda Calculus and want to see it illustrated with diagrams, pictures and Go code or

 • Manager of software projects and want to see a better correspondence between requirement gathering, implementation and testing or


 • C-level executive and want to understand what motivates and excites your IT staff or


Programmers:  If you are a…

 • Software enthusiast and want to learn Functional Programming or

 • Software tester and want to see a better correspondence between requirement gathering, implementation and testing or

 • Software architect and want to understand how to use FP or

 • Go developer and like soccer or

 • Go developer and want to implement your business use case programming tasks with more expressive code or

 • Go developer and want to understand Generics or

 • Java developer and would like to understand why we say, "Less is more." or

 • YOUR_LANGUAGE_HERE developer that knows FP and want to transfer your skills to Go or

 • Go developer looking for a better way to build data transformation pipelines or

 • Go developer and would like to see a viable way to write less code,  i.e., fewer if err != nil blocks or

 • Experienced Go developer and want to learn Functional Programming or add some tools to your toolbox or


 • Involved in software development and want to understand any of the terms below

… as long as you any of the above and willing to open your mind this book is for you.


If you are a Go developer looking for working code, with line-by-line explanations for any of the following…

Benchmark testing
Concurrency (Goroutines/Channels)
Currying
Data transformation pipeline
Decorator Pattern
Dependency Injection
Duck typing
Embedding Interfaces
Error handler
Function composition
Funcitonal parameters
Functors
Generics via code generation
Hollywood Principle
Interface driven development
I18N (language translation)
IoC
Lambda expressions in Go
Layered application framework
Log handler
Monads
Monoids
Observer Pattern
Partial application
Pipeline to process credit card payments
Recursion
Reduce function to sum invoice totals
Solve circular dependency errors
Table driven http API test framework
Type Class
Upload/download files to/from Google Cloud Buckets
Y-Combinator


this book is for you.

Wednesday, November 8, 2017

What you need for this book

This book:  Learn Functional Programming in Go


If you want to run the Go projects discussed in each chapter, you need to install Go.


If you're on a Mac go here.


Otherwise go here.


Next, you need to get your Go development environment running and start writing code.


Read the TL;DR subsection of the "How to build and run Go projects" section of the Appendix.


Go to chapter 1 in the book and start reading the section entitled, "Getting the source code"

Continue reading on how to setup and run your first project.


Other Go resources:

These will be the most helpful:


These examples will help you learn Go. After working through one or more of them look at the code from the book and ask yourself, "What's different?". (Hint: This older work would dinged for a few things during a code review.)   

You'll soon learn the best ways to code Go after a few projects in this book. 

Note: When I think of better resources later, I'll put that information here.






Tuesday, September 19, 2017

Characteristics of a Functional Programming Language

------------
UPDATE:  I added 10 more items to the list.  For all 27 see my book
------------

Let’s start by looking at requirements for a pure Functional Programming (FP) language. In a Pure FP language, a function...
  • when given the same input parameters always returns the same results
  • has no side-effects
Sounds good, but why is it valuable? Side-effects is one of the biggest barriers to parallelizing our applications. Modern computers have multiple cores and cloud-native applications scale horizontally where copies of same app runs on multiple servers. The ability to run your application reliably in a cloud environment. How’s that for value?

A pure FP language also includes support for things like:
  • Tail Call Optimization
  • High Order Functions
  • First Class Functions
In order to accomplish pure functional programming, a language must treat functions as it does any other variable type. How can an immutable language have variables that “vary”? The way we accomplish this in an FP way is by creating new variables, rather than modifying existing ones. To see this in action, check out the Map function example in my book, Learning FP in Go.

Go is a multi-paradigm language that supports imperative, object-oriented, and functional programming styles. We could write a purely imperative program in Go or a purely functional program in Go. Go gives us the freedom to choose our programming style. That's one of the great things about Go and FP. It's not an all or nothing issue. We can migrate our code towards FP when and where it makes sense to do so.

To fully support pure FP, Go requires Tail Call Optimization (TCO) to handle production performance requirements. Since each time a recursive function calls itself a new block is added in the stack frame, we soon feel the sluggish effects of this Go compiler omission. To see how we can mitigate this issue check out the Reduce function example in my book, Learning FP in Go.

High Order Functions (HOF) take functions as arguments and/or returns functions as its result. HOFs allow us to chain our functions together in a readable manner with less code.

HOFs are arguably the focal point of any FP language, and after a quick look at FP characteristics we’ll study how we can exploit them in Go.

Characteristic Supported in Go? Description
Referential Transparency
Referential transparency means that our function expression f(x) and the results of evaluating our function are interchangeable. For example, 1 + 1 is always equals 2.  This means that we can cache the results of the first function invocation and improve performance.

Tip: If we can cache results from previous function calls then we have referential integrity.
Idempotence
Idempotence  means that we can call our function repeatedly and it will produce the same result each time.
No Side Effects
“No side effects” means that the only thing that occurs when we call a pure function is: 1) we pass in parameters and 2) we  get a result; Nothing else happens.

Tip1: If our function prints output it is impure.

Tip2: If any state/data changes anywhere else in our system as a result of calling our function then our function is impure.

Tip3: If our function has no return value then it is either impure or completely useless.
Pure function
Pure function means that a function when given the same input will always return the same output and will not have any observable side effects.
Currying
Currying is where we get a function that accepts x parameters and return a composition of x functions each of which take 1 parameter.  In FP, every function is a function of one argument.  For more details and a code example see my book, Learning FP in Go.
Closures
A closure is an inner function that closes over, i.e., has access to, variables in its outer scope.  See example below.
Recursion
Recursion is used by FP languages in place of loops where a function calls itself until an end condition is reached. In Go, every recursive call creates a call stack. Tail-call optimization (TCO) avoids creating a new stack by making last call in a recursion the function itself. Even though we can code recursively in Go without TCO, it’s just not practical because of poor performance. Note that recursion in pure FP languages are abstracted from sight by HOFs.
Partial Function Application
Giving a function fewer arguments than it expects is called Partial Function Application. Here, our function accepts a function with multiple parameters and returns a function with fewer parameters.  For more details and a code example see my book, Learning FP in Go.
Parametric Polymorphism
Parametric Polymorphism means "Generics”.  This is a style of datatype generic programming where we code our functions using non-specific data types.  For example, we can implement generic algorithms that work on collections of non-specific types. Generics provides code reuse, type safety and easy-to-read code. See Generics section below for a simple example.
Operator Overloading
Operator overloading, also known as “ad hoc polymorphism”, is a specific case of polymorphism, where different operators like +, = or == are treated as polymorphic functions and as such have different behaviors depending on the types of its arguments.
Type Classes
Type classes allow us to define functions that can be used on different types with a potentially different implementation for each type. Each class represents a set of types and is associated with a particular set of member functions. For example, the type class Eq represents the set of all equality types, which is precisely the set of types on which the (==) operator can be used. For more details and code examples (in Haskell) see my book, Learning FP in Go.
Hindley-Milner Type System
HM infers types without requiring any type definitions.  HM type systems support polymorphic types, where lists can contain items of different types.  If Go used HM, then the type of b would be inferred as “float64” below (rather than throwing the runtime error, “constant 1.8 truncated to integer”)

        a := 1
        b := a + 1.8
Use of Expressions
Declarative style, as opposed to Imperative, means that we write expressions, as opposed to step by step instructions. Tip: If we can call a function without using its return value then it’s impure.
First Class Functions
First Class Functions can be passed around as parameters and returned as values.
High Order Functions
High Order Functions can take functions as arguments and can return functions. For more details and a code example see my book, Learning FP in Go.
Tail Call Optimization
Tail Call Optimization makes recursive function calls performant.  A tail call happens when a function calls another as its last action. TCO acts like a GOTO statement.  Example:
  func f(x) {// some code;return g(x)}
The program does not need to return to the calling function when the called function g(x) ends b/c there is no executable code after that last line.  After the tail call, the program does not need any call stack information about g.  Without TCO the program will create a needless call stack for g;  A lot of recursive calls will cause a stack overflow.  With TCO, the recursive  program will be faster and consume far fewer resources.
Unit Type
A unit type has exactly a one value. It is also known as the identity. The unit for multiplication is 1, for addition is 0, for string concatenation is the empty string.

How many values can a type defined as a tuple of of type int contain? Infinite. (-∞, …, 0, 1, 2... ∞)

How many values can a type defined as the empty tuple contain? One. ()

The value of a unit type is that you can use it in places where we might otherwise return nil (or null). We return a unit when we don’t care what the value is. We don’t return nil, we return a value; the unit value. All functions return values; No more null pointer exceptions!

The 's indicate that the FP characteristic exists in Go.

The 's indicate that characteristic can be achieved with some effort in Go.

The 's indicate that this FP characteristic is missing or is difficult or not possible to achieve without a major upgrade to the Go compiler or without using another technology in tandem with Go.

Let’s look closer at a few characteristics of functional programming in Go...

A closer look at f(x)

Let's examine a basic function definition. "f" is the function name. "x" is the input value. Another name for "x" is the input parameter.

The entire expression "f(x)" represents the output value.


If f(x) = x + 1, then we know that every time we input the value 2, 3 will always be the output value. In other words, a pure functional program always produces consistent results and never has any side effects.

Generics

Parametric Polymorphism means "Generics". A generic function or a data type can be written so that it can handle any data value using the same logic without having to cast the value to a specific data type. This greatly improves code reuse.

Below, is a C# code example of a generic IsEqual implementation. The generic IsEqual function will accept any type (that implements Equals). We could pass IsEqual integers and strings by simply indicating the type "T" during runtime at the moment that IsEqual is executed. We could easily extend IsEqual to support domain entities like cars.
namespace Generics
{
  private static void Main() {
     if(Compute.IsEqual(2, 2)) {
           Console.WriteLine("2 isEqualTo 2");
        }
     if(!Compute.IsEqual("A", "B")) {
           Console.WriteLine("A is_NOT_EqualTo B");
        }
  }
   public class Compute {
       public static bool IsEqual(T Val1, T Val2) {
           return Val1.Equals(Val2);
       }
   }
}


Currently, to do this in Go we would have to use the empty interface and perform a type conversion. It's that type conversion that will cause the performance hit that usually makes this sort of generics handling in Go impractical.

First class functions

First class functions allow us to make new functions by providing our base functions with functions parameters. Below, our base function is Filter. By passing ByMake("Toyota") to Filter we remove most car items from our collection, leaving only Toyotas.

cars := Filter(ByMake("Toyota"))
We also have the ability to transform any function that works on single elements into a function that works on lists by wrapping it with the Map function. Without our new functional style of programming we might be tempted to implement a for loop and apply the fmt.Sprintf transformation on each individual car as follows:

for _, car := range cars {
      thisCar := fmt.Sprintf("%s %s", car, map[string]string{
             "Honda": "LX",
             "Lexus": "LS",
             "Toyota": "EV",
      }[GetMake(car)])
      mappedCars = append(mappedCars, thisCar)
}
Instead, we can simply pass the Upgrade function to Map as we compose our data transformation:
Filter(ByMake("Toyota")).Map(Upgrade())
We no longer need to write for loops that manipulate arrays because we can call Map inline. HOFs can greatly reduce the time that it takes to develop complex logic. We can quickly compose smaller, task-specific functions into solutions for complex business logic much faster, with less scaffolding code, which means we’ll have fewer bugs to fix. Our functions are in essence reusable building blocks.

HOFs are independent , making them easy to reuse, refactor, and reorganize in our code base. This makes our programs more flexible and resilient to future code changes. More readable code, faster implementation, fewer bugs… The benefits of FP are adding up!

Closure

A Closure is a function that closes over variables in its outer scope. We really need an example to understand that statement! Here's a good one:
func addTwo() func() int {
      sum := 0
      return func() int {  // anonymous function
             sum += 2
             return sum
      }
}

func main() {
      twoMore := addTwo()
      println(twoMore())
      println(twoMore())
}

Output:

2
4
The closure above is formed by the addTwo function. Inside addTwo, both sum and the anonymous function are declared in the same lexical scope. Since addTwo closes over both sum and the anonymous function and because sum was declared before the anonymous function, the anonymous function always has access to, and can modify, the sum variable. As soon as addTwo is assigned to twoMore, addTwo’s anonymous function gets access to the sum variable and holds on to it as long as the application continues to run.

Being able to pass around context is powerful. In the Learning FP in Go book, we’ll look at a practical example where we create an application context, e.g., database connection, logger, etc. at application startup and pass that context around where needed throughout our application.

Pure function

Pure function means that a function when given the same input will always return the same output and will not have any observable side effects. How is that a benefit? You may ask. Let’s see...

Side effects are one of the biggest barriers to parallelizing our programs because we can't reason about changes to a global state. If we manage state outside of our imperative functions and must perform steps in a particular order, how do we accomplish our sequenced tasks across multiple servers in our cluster? That’s not an easy problem to solve.

Pure functions, on the other hand, do not require access to shared memory and cannot create race condition because they have no side effects. The simplicity and performance gains of relatively easily running our code concurrently provide more reason to design our applications using the FP paradigm.

Use of expressions

Use of expressions (rather than statements) means that in FP, we pass a value to a function that typically transforms it in some way and then returns a new value. Since FP functions have no side effects, an FP function that does not return a value is useless and a sign of code smell. In Chapter 1 of Learning FP in Go, we saw that imperative programming focuses on the step-by-step mechanics of how a program operates. Whereas, in declarative programming we declare what we want the results to be.

Imperative:

var found bool
carToLookFor := "Blazer"
cars := []string{"Accord", "IS250", "Blazer"}
for _, car := range cars {
      if car == carToLookFor {
             found = true;
      }
}
fmt.Printf("Found? %v", found)

Declarative:

fmt.Printf("Found? %v", cars.contains("Blazer"))
That’s less code that is easier to read.

Summary

In this article, we looked at the requirements and characteristics of Functional Programming and illustrated a few using Go implementations such as:
  • Functional Composition
  • High Order Functions
  • Closures
  • Expressions
FP is a programming style that is declarative. It is more readable and usually requires much less code than other imperative or object oriented implementation options.

To find out more about why FP is well suited for cloud deployments and how FP helps us manage the complexity of software development, get a copy of Learning Functional Programming in Go.

p.s.

I hope this book preview answered a few functional programming questions you might have had. I also hope you consider purchasing a copy of my book. It has a few thing that you likely won't find anywhere else, like:
  • A visual, example laden introduction to Category Theory (*)
  • A working understanding of Lambda Expressions (in Go)
  • A better dependency management using Glide (and a dash of Bash Kung Fu)
  • A children's story about a duck's life (in Go)
  • A plethora of real world examples and illustrations
  • A unique empowerment to build better, more composable applications in today's distributed environments

A visual, example laden introduction to Category Theory (*)

This is my book's largest chapter (over 100 pages). My goal in this chapter is to deliver a deep appreciation for category theory with as many code examples, diagrams, tables and illustrations as it takes for you to really "get it".

We'll discover fundamental truths. We'll see and understand the connection between category theory, logic, lambda calculus, flow based programming and the world around us. We'll learn how to turn software development complexity into simplicity via (de)composition. (With code examples in Go and a few in Haskell, Javascript and Ruby.)

Would you like to understand the following?
A monad is just a monoid in the category of endofunctors, what's the probleⅿ?
Last but not least, we'll learn to appreciate our elementary, middle school and high school math classes. They weren't useless after all! (Read my book and send your old math teachers some love).

p.s.s.

Thank you for buying my book!



This work is licensed under the Creative Commons Attribution 3.0 Unported License.