DEV Community

Ryan Frazier
Ryan Frazier

Posted on • Originally published at pianomanfrazier.com on

What Is Functional Programming

In my day to day work as a software engineer I do not have the luxury of using a functional language like Haskell or Elm, however I have learned a lot from Elm that has changed how I program in JavaScript or Python. Here is a run-down of some of the concepts I have learned from writing 3000+ lines of Elm code.

Here are some of my projects written entirely in Elm.

FP Vocabulary

Here is a list of common terms that come up when learning functional programming (FP). I will discuss many of them in this article.

  • Pure Function
  • Side Effect
  • Referential Transparency
  • Mutable/Immutable
  • Currying
  • Monad
  • Algebraic Data Types
  • Variant
  • Lambda Calculus

Pure Functions

What is a pure function?

A function is said to be pure if 1) given the same arguments it always returns the same result and 2) the function has no side effects.

function add(a,b) {
  return a + b;
}
function impureAdd(a,b) {
  return a + b + c;
}
console.log(add(1,2)) // 3
// console.log(impureAdd(1,2)) // EXPLOSION!!!
c = 1
console.log(impureAdd(1,2)) // 4
c = 2
console.log(impureAdd(1,2)) // 5
Enter fullscreen mode Exit fullscreen mode

What is a side effect?

A side effect is something that occurs as a result of a function call that does not get returned from the function.

Referential Transparency

An expression is said to be referentially transparent if the evaluation of the function can be replaced with its return value and not effect the program's behavior.

result = add(2,3) + 5 // result == 10
result = 5 + 5 // result == 10
Enter fullscreen mode Exit fullscreen mode

By contrast, if the function call cannot be replaced by the output then the function is said to be referentially opaque.

No For Loops?

In a pure functional language like Haskell or Elm, you will notice there are no for loops. You must process all lists with map, reduce, and filter (among others).

list = [1,2,3,4]
// Imperative
listTimesThree = []
for(i = 0; i < list.length; i++) {
  listTimesThree.push(list[i] * 3)
}
// Declarative
listTimesThree = list.map(x => x * 3)
Enter fullscreen mode Exit fullscreen mode

What are all the things that could go wrong in a for loop?

  • mental burden of parsing a for loop (What does it do? Is it correct?)
  • thread mutate the processing list
  • mutate the iterator variable i
  • out of range list access

Currying

currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument.

Wikipedia Currying
add = a => b => a + b
addOne = add(1) // What does this return?

add(1)(2) // 3

list.map(x => addOne(x)) // [2,3,4,5]
Enter fullscreen mode Exit fullscreen mode

How is currying useful?

How about providing different ways to render a list? Currying makes it easy to make functions from other functions.

list = ['Fries', 'Hamburger', 'Shake']

latexListHead = x => `\\begin\{itemize\}\n${x}\n\\end\{itemize\}`
latexItem = x => `\\item ${x}`

htmlListHead = x => `<ul>\n${x}\n</ul>`
htmlItem = x => `<li>${x}</li>`

mdListHead = x => x // The identity function
mdItem = x => `- ${x}`

renderList = headFn => itemFn => list => headFn(list.map(x => itemFn(x)).join('\n'))

latexList = renderList(latexListHead)(latexItem) // LaTeX render function
webList = renderList(htmlListHead)(htmlItem) // HTML render function
mdList = renderList(mdListHead)(mdItem) // Markdown render function

console.log(webList(list))
console.log(latexList(list))
console.log(mdList(list))
Enter fullscreen mode Exit fullscreen mode

Now what if you wanted several styles of lists, like a fancy web list.

htmlListHead = classes => x => `<ul class='${classes.join(' ')}'>\n${x}\n</ul>`

bigBlueListHead = htmlListHead(['big', 'blue'])
smallRedListHead = htmlListHead(['small', 'red'])

webList = renderList(bigBlueListHead)(htmlItem)

console.log(webList(list))
Enter fullscreen mode Exit fullscreen mode

There are other uses for currying like generating a range of math plots. See my post on creating beautiful math homework. And here is the python file

Exception Throwing is a Side Effect

The reasoning is that I consider exceptions to be no better than “goto’s”, considered harmful since the 1960s, in that they create an abrupt jump from one point of code to another. In fact they are significantly worse than goto’s

  1. They are invisible in the source code.
  2. They create too many possible exit points for a function.
Joel Spolsky at Joel on Software

I wrote about this topic in a previous blog post Exceptions Considered Harmful.

JavaScript helper libraries

JavaScript is notorious for an inconstant API. What functions are immutable? For example, map() creates a new array whereas sort() and reverse() mutate the array in place and returns the mutated array. This inconsistency is a mental burden. Therefore there is a need for libraries like Ramda.

list = [4,2,3,1]
sortedList = list.sort()
console.log(list) // [4,2,3,1] or [1,2,3,4]?
Enter fullscreen mode Exit fullscreen mode

Compare with Ramda's sort.

JS Libraries

TypeScript Libraries

Other Resources

Top comments (0)