# Defining Functions

← Previous in this series: What is FP?

In the previous chapter, we’ve established the very basics of what is FP, and tried to dig a bit deeper in what “programming with functions” means.

In this chapter we’re going to try to establish what functions are, how
they’re defined differently in different domains and what do we mean by
*function* in functional programming.

# What are functions?

In programming, the idea of function differs greatly from the idea of a function in mathematics, so let’s first try to establish this difference.

## Functions in programming

In programming, what is normally called a *function* is a subroutine. This
basically means it’s a (somewhat) closed code block containing sequences of
language instructions. These *functions* can take parameters and can return
values, which might be solely based on the input parameters or not.
An example of this, using Scala, could be (please ignore all the horrible ways
this code could go wrong, the deprecation, and all the unnecessary steps that exist
here for the sake of simplicity and example):

```
def foo(x: Int) = {
val y = readLine("Enter a number: ")
val n = x + y.toInt
println(s"$x plus $y is {$n.toString}")
}
```

This would read some input from STDIN, convert it to an integer, add 2 to it, and then print it to STDOUT.

## Functions in maths

Because the objective here is to learn about FP, not maths, I’m going to try
to focus on how they differ from the concept of *function* that developers are
more familiar with, rather than anything else.
In maths, functions are mapping from a set o values to another set of values.
This boils down to being an expression that can be reduced to a value, by
applying the parameter values and reducing the expression.
A representation of this, in programming, using Scala syntax could be something
like:

```
def add(x) = x + 3
```

What this implies is, if you replace `x`

with a value, let’s say `2`

, you can
perform variable substitution in the expression, which gives you `2 + 3`

, and
then you can reduce it, which will give you a value, `5`

.

## functions vs functions

In our first example, we see that we have a sequence of instructions, while on
our second example we have only a single expression. We also see that
for `println`

, we don’t even care about its return value, and furthermore for
`readLine`

we don’t depend on the input parameters but rather on run-time user input.
This means that there’s a lot of things going on in our programming function that
couldn’t happen in the maths definition of functions, it being a mapping between sets
of values.

This brings us to the difference between an expression and a statement.

# Expressions vs Statements

Well, there’s really not a lot to say about this at this point. In `x + 3`

we
can replace the variables by the function parameters, and reduce the
expression by applying the operations on the values until we have a single
value. In `println(s"$x plus $y is {$n.toString}")`

we’re giving an instruction
to perform some output, we can’t apply variable substitution, reduce it, and
in languages that actually implement it as a statement get a value out of it
(Scala does return a value and implements it as a function, but more on that
on the next chapters).
The former is an *expression*, the latter a *statement*.

# Why is this distinction useful?

I’m glad you asked. There’s a number of reasons why this distinction is useful, let’s talk about some of them.

## Reasoning

If you can apply variable substitution and reduce an expression, and nothing else, this gives you a very powerful tool to reason about that expression. Armed with this knowledge, you can establish the mapping between the input and output values. This is not true for statements, as they might depend on third parties (such as user input), or not even do a mapping at all.

## Local Reasoning

The previous property also gives you what’s often called local reasoning. If all you can do is apply variable substitution and reducing by applying the operations in the expression, you don’t need to keep other parts of the system in your mind. Again, this is not possible with statements because they depend on the outcome of the instruction given by the statement.

## Partial Reduction

This one might be a hard one to understand if you’ve not come across this sort of thing before, but bear with me for a second.

Let’s say you have the following expression:

```
x + 2 + y
```

Let’s also say that you know that `x = 5`

but you don’t know the value of `y`

.
You can still apply variable substitution, and so you get `5 + 2 + y`

. But if
you look at the resulting expression, you might see that we can still do some
reduction by applying the `+`

operation, resulting in `7 + y`

. Because you still
don’t know `y`

, you’ll have to stop here. This means that by reducing an expression
you can also get a simpler expression, not just values.

## Every input maps to an output

If an expression can always be reduced into a simpler expression or a value, it means that we know that there’s never a situation where we get nothing out of an expression. This might sound like a no-brainer, but being able to know that we always get something that we can use, is an important property that we can rely on.

## Composability

Expressions are combinations of values and operations on those values, which
can eventually be reduced into other values. This means you can create more
complex expressions by composing simpler ones (ex: ```
2 + (5 * x) - (2 / y +
z)
```

).

## Perform outcomes

This is where statements come into. If an expression allows you only to perform variable substitution and operation application, then you can only transform them into simpler expressions or values, but you can’t make them cause a change in the world.

# Functions in programming

We see by the previous examples, that in general, in programming languages functions can be made of expressions, statements or combinations of both.

In Pascal, there used to be two types of subroutines, the *function* and the
*procedure*. The main difference between the two, is that functions have a
return value and procedures don’t. Most languages don’t make this distinction
and just return `void`

instead.
While not enforced in any way in Pascal, it is useful to think about why functions
that have a return value are so different from the ones that don’t, that would
warrant these two constructs.

It seems like procedures fit better with the model where we chain statements
to perform actions, and we don’t always (sometimes we do want an exit code or
similar, but more often than not, the last statement’s output is ignored)
really care about a return value (look at our `foo`

function, we don’t really
return anything useful out of it), while functions fit better the model where
we define expressions and map from the input parameter values to the output values.

The lack of a first class construct to distinguish between those two different things, is a huge hindrance in making developers aware of this difference. Languages like Haskell address this difference in a way that we’ll look into in the next chapters.

As a side note, these procedure like functions with no return type, usually
expressed through `void`

, are usually handled through the type system in typed
functional languages, by returning a value of type `Unit`

, which represents a
type that can have a single value (unit), and therefore carries no information.

# How does any of this relate to FP?

Remember on the previous chapter I said that FP is all about injecting functions? Well, turns out that if your functions are made of these expressions that depend only on the input parameters to generate their output, then your functions also inherit those properties I described above (easy and local reasoning, allow partial application, can be trusted to return something, and are composable). This means you can build complex behaviours by composing smaller functions with simpler behaviours while being able to reason about each of those functions individually.

## But then, how can I make the computer actually “do things”?

In most functional languages, functions are not inherently made exclusively of
expressions (they are in Haskell where functions are a single expression but it
provides constructs *where* it *lets* you set up auxiliary
values/expressions).

In most functional languages you are encouraged to separate functions that perform these actions and push them to the edges of the system. This is, again, not unlike the popular OO strategy when doing Domain Driven Development, of modeling input and output sources as interfaces at the boundary of the system.

In Haskell, this is addressed explicitly, and by default you can only perform these actions inside of something called an effect system (Scala also has a few effect systems available via 3rd party libraries namely cats.effect.IO and ZIO). Effect systems are part of what makes functional programming so powerful.

However, effect systems are outside of the scope of this chapter, and will be addressed in a later chapter.

# Wrap Up

Next time, we’ll talk about some properties of functions, which are very closely related to the concepts we’ve talked about here.

If you'd like to keep up to date with new posts, follow me on twitter @mpmlopes ,

or subscribe to the feed.