# Converting Temperature Units

Life is far too important a thing ever to talk seriously about.

To kick off our Ramda journey, we're going to do something ridiculous: transform very clear temperature conversion functions that use JS math operators to use only functions for the operations!

Sometimes, when we forego the obvious and choose to approach problems in different ways, interesting patterns may emerge that can expand our understanding.

Let's get introduced to some perfectly fine conversion functions — one of which we are going to rip apart and make anew.

``````function celsiusToFahrenheit(celsius) {
return celsius * (9 / 5) + 32
}

function fahrenheitToCelsius(fahrenheit) {
return 5 / 9 * (fahrenheit - 32)
}

function easyCelsiusToFahrenheit(celsius) {
return celsius * 2 + 30
}

function easyFahrenheitToCelsius(fahrenheit) {
return (fahrenheit - 30) / 2
}
``````

While the `celsiusToFahrenheit` and `fahrenheitToCelsius` functions are exact formulas, they're not practical for everyday use. I've lived in the UK and New Zealand, and since I'm married to a Kiwi, I need to easily convert between Celsius and Fahrenheit. While not exact, the `easyCelsiusToFahrenheit` and `easyFahrenheitToCelsius` formulas are easy to do in one's head and are close enough to the real values.

We are going to single out `celsiusToFahrenheit` for this extended example.

``````function celsiusToFahrenheit(celsius) {
return celsius * (9 / 5) + 32
}
``````

## Enter the Ramda

In it, we:

1. multiply the Celsius value by the result of `9 / 5`
2. add `32` to the result of the prior step(s)

Before we go further, let's first convert it to an arrow function expression, for doing so will open some interesting doors.

``````const celsiusToFahrenheit = celsius =>
celsius * (9 / 5) + 32
``````

Next, let's get Ramda pulled into the picture.

Ramda has a number of math functions, namely `multiply`, `divide`, and `add` that we can leverage in place of `*`, `/`, and `+`. Each function takes two arguments, and each function will wait to evaluate itself until you provide all the arguments. Check this out:

``````add(1, 2)     // 3
``````

This is indeed weird, and we'll cover this fully in the "Core Ramda Ideas" section.

For now, let's import those and use them!

``````import { add, divide, multiply } from 'ramda'

const celsiusToFahrenheit = celsius =>

celsiusToFahrenheit(100) // 212
``````

Woah, woah, woah! What's going on here?!

It looks like we're...

1. adding `32` to the result of
2. multiplying the Celsius value by the result of dividing `9` by `5`

That's the same process we did before, but it's merely explained differently!

With addition and multiplication, there's something called the commutative law that states we can provide the arguments to an addition and multiplication operation in any order. Let's leverage this law in order to move our variable, `celsius`, further toward the edge of our function to judge how it feels.

``````// this is what we're starting with

// first, swap `celsius` and `divide(9/5)`
//               ^------------^

// next, swap the multiplication and `32`
//  ^------^

// the result
const celsiusToFahrenheit = celsius =>
``````

Interesting! Do you see it yet? The forwarding of a result from function to function? Let's look at this another way:

``````const celsiusToFahrenheit = celsius => {
const multiplied = multiply(divide(9, 5), celsius)

}
``````

We provide `celsius` as the second argument to `multiply`, then we provide the result of that as the second argument to `add`. We're simply forwarding the evaluated result of a computation to another function; kind of like passing an electric guitar's signal through a few effects pedals and then out the amplifier.

What if we had a cleaner way to link these functions together so we can easily understand what `celsiusToFahrenheit` is composed of and then provide the data at the end?

It's time to take this first lesson into overdrive.

## A Taste of Composition

We need a way of passing the result of calling one function to another function and having that run. It'd be easier if we could abstract an API... let's try that.

``````// this is essentially what we have
// with our celsiusToFahrenheit
f2(f1(value))

// but we want something like this;
// let's call it `link` because
``````

With that desired outcome in mind, let's try to write `link`!

``````const link = (f2, f1) => value =>
f2(f1(value))
``````

Ha! We're still doing the difficult to follow `f2(f1(value))`, but now we can use this like `link(f2, f1)(value)`.

Circling back to `celsiusToFahrenheit`, let's try to use this `link` abstraction:

``````// before
const celsiusToFahrenheit = celsius =>

// after
const celsiusToFahrenheit = celsius =>

celsiusToFahrenheit(100) // 212
``````

Nice! We can now do a little less inside-out reading. But something doesn't feel quite right... Why are we accepting the argument `celsius` in our `celsiusToFahrenheit` function only to turn right back around and call `link()` with the `celsius` value? Do we need it?

Nope.

``````// before
const celsiusToFahrenheit = celsius =>

// after
const celsiusToFahrenheit =

celsiusToFahrenheit(100) // 212
``````

You may be wondering why `link` reads right to left. Two short answers are:

1. Mathematics writes `f(x)` and not `(x)f`
2. Evaluation is done from right to left (inside -> outside), so we are right-associative

However, let me ease your worried mind and make a `linkL` (`L` for "left") function for us to use:

``````const linkL = (f1, f2) => value =>
f2(f1(value))
``````

And when we compare that to the original function, we realize that we've come nearly full circle but with a whole new perspective:

``````// where we started
const celsiusToFahrenheit = celsius =>
celsius * (9 / 5) + 32
//        ^    ^    ^
//  multiply   |    |
//           divide |

// where we ended up
const celsiusToFahrenheit =
``````

Ramda provides a few functions, `compose` (or `o`) and `pipe` that do the `link` and `linkL` work for us!

``````import {
compose,
divide,
multiply,
pipe,
} from 'ramda'

// `compose` and `o` are very similar
const celsiusToFahrenheit =

// `pipe`
const celsiusToFahrenheit =
``````

We'll cover function composition a bit more in the "Core Ramda Ideas" section.

Can you convert the remaining temperature conversion functions to use Ramda functions? Give them a try in a pre-loaded Ramda REPL.

Here they are again, in case that link doesn't work:

``````function fahrenheitToCelsius(fahrenheit) {
return 5 / 9 * (fahrenheit - 32)
}

function easyCelsiusToFahrenheit(celsius) {
return celsius * 2 + 30
}

function easyFahrenheitToCelsius(fahrenheit) {
return (fahrenheit - 30) / 2
}

const result = () => ({
'212F = 100C': fahrenheitToCelsius(212),
'25C ≈ 80F': easyCelsiusToFahrenheit(25),
'60F ≈ 15C': easyFahrenheitToCelsius(60),
})

result()
``````

When you're done, compare them against my solutions!

Expand this to see my solutions if the link doesn't work
``````//function fahrenheitToCelsius(fahrenheit) {
//  return 5 / 9 * (fahrenheit - 32)
//}

// This is the best I could do before I had to cheat... see below!
//const fahrenheitToCelsius = fahrenheit =>
//  multiply(divide(5, 9), subtract(fahrenheit, 32))

// If you're feeling clever, check this out:
// https://ramdajs.com/docs/#__
const fahrenheitToCelsius =
compose(multiply(divide(5, 9)), subtract(__, 32))

// ===============================================================

//function easyCelsiusToFahrenheit(celsius) {
//  return celsius * 2 + 30
//}

// Step 1:
//const easyCelsiusToFahrenheit = celsius =>

// Step 2:
const easyCelsiusToFahrenheit =

// ===============================================================

//function easyFahrenheitToCelsius(fahrenheit) {
//  return (fahrenheit - 30) / 2
//}

// This is the best I could do before I had to cheat... see below!
//const easyFahrenheitToCelsius = fahrenheit =>
//  divide(subtract(fahrenheit, 30), 2)

// If you're feeling clever, check this out:
// https://ramdajs.com/docs/#__
const easyFahrenheitToCelsius =
compose(divide(__, 2), subtract(__, 30))

// ===============================================================

const result = () => ({
'212F = 100C': fahrenheitToCelsius(212),
'25C ≈ 80F': easyCelsiusToFahrenheit(25),
'60F ≈ 15C': easyFahrenheitToCelsius(60),
})

result()
``````

## Wrapping Up

This turned out to be far from a gentle introduction!

We started with some addition, division, and multiplication to convert temperature values, and we ended up walking backwards into the heart of functional programming.

Way to go!