38

It seems like, when reading something like this Wikipedia article about "pure functions", they list Today() as an example of an impure function but it seems pretty pure to me. Is it because there is no formal input argument? Why is the actual time of day not treated as the "input to the function" in which case if you gave it the same input, i.e. executed today() twice at the same time, or traveled back in time to execute it again (maybe a hypothetical :) ), the output would be the same time. Today() never gives you a random number. it always gives you the time of day.

The Wikipedia article says "different times it will yield different results" but that's like saying for different x sin(x) will give you different ratios. And sin(x) is their example of a pure function.

6
  • 8
    If you passed in the time of day, what would the function do?
    – JB King
    Jan 23, 2013 at 15:56
  • 1
    I'd expect it to give you the time of day. (not the most useful function). But it doesn't have any argument, which I think is the root of the answer.
    – Brad
    Jan 23, 2013 at 15:59
  • 3
    Can you predict its output (based on the input parameters you provided)?
    – Daniel B
    Jan 24, 2013 at 6:15
  • 1
    @DanielB There is no predictive power to the absent/null input parameter it turns out. The only thing I can do is look at my wrist watch (jk my cell phone).
    – Brad
    Jan 24, 2013 at 13:31
  • "Why is the actual time of day not treated as the "input to the function"" This is, basically, the problem that monads try to solve. Pure functions can only be based on their inputs & can have no side-effects. If you make the "state of the world before me" an input and "state of the world after me" part of the return value & pass these world states through your program, you can once again be pure. Jan 24, 2013 at 19:25

10 Answers 10

105

Is it because there is no formal input argument?

It is because the output depends on something that is not an input, namely the current time.

Why is the actual time of day not treated as the "input to the function"

Because you didn't pass it as a parameter. If you did pass it in as a parameter, the function would become an identity function on dates, which is pretty useless. The entire point of a Today() function is to output something that depends on an external and constantly changing value (time).

The advantage of pure functions is that their behavior is absolutely reproducible and deterministic, making it easy to have formal proofs and hard guarantees. They always do the same thing. Today() is pretty much the opposite: it always (allowing for time granularity) does something different.

6
  • 2
    So even though the time of reality is sort of an input, because it's is not given as an input and it is outside of the control of the function (both internally to the function and outside the control of whoever is calling Today()) Today() becomes impure. The Today() function might be a bit of a silly example. More appropriate might be some Count() function. Given the same number of items to count Count() will always return the same number, but since that is outside of the scope of Count() it is impure.
    – Brad
    Jan 23, 2013 at 16:22
  • 1
    @brad that's somewhat of a gray area - there is a implicit actual argument - the array or list. Given an immutable list and the same argument each time it will always return the same value.
    – Max
    Jan 23, 2013 at 16:28
  • 34
    "the time of reality is sort of an input" - yes; indeed, the global state is implicitly available (ie 'sort of an input') to all functions, but if they depend on it for their result they are impure!
    – AakashM
    Jan 23, 2013 at 16:34
  • 4
    @Brad count() on most programming languages is definitely pure. It has an explicit input value: the collection whose count you want. Don't be confused by a syntax such as myCollection.count(); that's just sugar for count(myCollection).
    – Andres F.
    Jan 24, 2013 at 22:39
  • Great answer as always, but it doesn't explicitly cover immutable free variables. They're not an input to the function -- not passed as a parameter -- but the function depends on them even if it's still referentially transparent.
    – user39685
    Apr 7, 2014 at 15:25
24

sin(x) will always return the same value, as long as x stays the same. Today() could return different results over time because it depends on values outside of your control. For example, if something beyond the control of your program changes the system's internal $current_datetime while your program is running, Today() will suddenly yield different results.

8
  • "will always return a different value" is a bit... impure wording. Wikipedia says "returns the current day of the week" meaning that values obtained on Mondays won't differ
    – gnat
    Jan 23, 2013 at 15:25
  • 7
    @gnat: True, unless something external to your program changed your computer's internal calendar so that it suddenly thought it was Thursday. Then calling Today() would return "Thursday" on a Monday. Jan 23, 2013 at 15:28
  • 3
    @gnat Well, it won't always return a different value (there's hardly any useful function that does). But, like most impure functions, the return value can vary even during execution of a single program (e.g., if it runs overnight).
    – user7043
    Jan 23, 2013 at 15:46
  • 3
    @delnan: Yes, that is the bane of naive database script authors! :P "But HOW could it miss 300 records? The script worked fine when I tested it yesterday morning!" Jan 23, 2013 at 15:49
  • @delnan that's for sure. I only pointed out that using always in the initial wording (corrected in current version answer to could) was somewhat imprecise
    – gnat
    Jan 23, 2013 at 15:53
13

Today() is an impure function because its result is dependent upon something that you do not give it; specifically, the current system time. Therefore, its result is not deterministic when based only on the inputs provided at invocation.

A pure function would be int Add(int a, int b) {return a + b;}. The function works solely with what it is given, and uses no other external state data. The natural result of this is that you can Add(2,2) and get 4 from now until the end of time. In addition, because the function doesn't change any external state (it has no "side effects"), Add()ing 2 and 2 from now until the end of time won't change anything else in the system, unless you then assign the result of the function to a variable or otherwise use the value to update state (which is not an operation performed by the function itself). Virtually all classical mathematical operations are pure functions and can be implemented as such.

Today(), on the other hand, may produce the same value when called two times in a row, but not if called repeatedly for several days. This is because it is dependent on external state data which is not provided by you as a parameter to the function. As a result, it is impossible, within the boundaries of the program, to control the result of the Today() function. It will produce a given value on a given day, and will never produce that value on any other day, unless you change the system clock of the computer on which it is run (a change generally occurring outside the boundaries of the program).

An impure function is not necessarily a bad thing; impure functions are required, even in functional languages, to interact with anything outside the boundaries of the program, such as data stores, communication pipelines, UI displays, peripheral devices, etc. A program that does not do any of these things is a program that is sharply limited in its utility; I would even go so far as to call such a program trivial, as without any means to accept input or any avenue to inform you of its output, it might as well be doing nothing. Programs written in functional languages can have only the input provided by the runtime and produce an output reported to the runtime without any explicitly defined impure methods, but that's because the runtime is abstracting away all these impure details of working within an imperfect computer system, so that the program itself can be structured in terms of a nested set of mathematical expressions that the runtime then evaluates given initial input.

It is simply a Very Good Thing to know which of the functions you are using are pure and which ones are not, so that you can make good decisions about how they are used. Impure functions, because they do things or are dependent on things that are not apparent from their usage, may behave unpredictably given only knowledge of the usage. Further knowledge of the purpose of the function, and thus what it needs from or does to external state, is required in order to place a system that uses it in a consistent state and thus to expect a deterministic result.

8

It seems fairly obvious that this function fails the first test of purity given at the very start of that page:

  1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change as program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.

Note that since it takes no arguments, there is only one possible set of argument values - the empty set. And this function can and does return different results for the same 'argument value(s)'.

Furthermore, the function result value does depend on "hidden ... state that may change as program execution proceeds". So another failure.

2
  • @JörgWMittag I'm not sure where I assert that a function with no arguments cannot return a value.
    – AakashM
    Jan 23, 2013 at 16:12
  • Brain fart. I read "there is only one possible set of return values". Jan 23, 2013 at 16:22
8

() => 1 would be a pure function, since it always returns 1. Today() may return "Monday" or "Tuesday" or nearly any other value.

Another way to think of it is pure functions don't depend on state. The world is typically considered state. You need to know the state of reality to know what day today is.

However you don't need to know anything special about the state of the world to know what sin(x) is. And ever call to sin(x) for a given x will return the same value.

2
  • Wikipedia says "returns the current day of the week", meaning it can return Monday, Tuesday etc but not "1/23/2013" nor "1/24/2013"
    – gnat
    Jan 23, 2013 at 15:31
  • 7
    @gnat: Updated, but the difference wasn't really material.
    – Guvante
    Jan 23, 2013 at 16:11
2

Date(timestamp) would be a pure function. Because of its idempotency. And because there would be no side-effect.

Today() can vary its result depending on when you call it. That's what makes it impure. It's not idempotent. It has no side-effect though, but that doesn't make it pure.

2

Here's a little pseudo code that I think of when discussing pure functions

newValue = Function();
while(true)
{
   oldValue = newValue;
   newValue = Function();
   assert( newValue == oldValue );
}

If that runs indefinitely and the can never trigger the assert, it's a pure function. More so, if you have a function that uses args, then a little modification....

oldValue = Function( importantVariableToYourApp );
newValue = Function( importantVariableToYourApp );
assert( newValue == oldValue );

If you can use that after every variable assignment in your app, and it doesn't change results in your app, and it can never fail the assert, then it is a pure function.

2

First, there is no such thing as a function without argument (or an array without indexes or a map without keys). It is the defining characteristic of a function to map one or more argument values to another value.

Hence, today is either not a function at all, hence no pure function. Or we may interpret the syntax

today()

a bit so that it means

today   ()      -- today, applied to the value ()

In Haskell, for example, this would be valid:

data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving Show
today :: () -> Day
today () = ....?
main = print (today())

because there is a type () with a single value ().

The question is only, how can today compute the day of the week, if it only has ()? It is just not possible without reading the system timer, directly or via helper impure functions.

The system timer is an excellent example for global state.

1

The problem with today() is that it can yield a different result if called two or more times in a function.

Here is a code example, that could introduce a bug.

function doSomething(when)
{
     if(today() == when)
     {
           // open a resource or create a temp file.....
     }

     // do some other work

     if(today() == when)
     {
           // close the resource or delete temp file.....
     }
}

It's possible in the above example. That the second if statement will not execute. Even if the first one did. Leaving a resource in a bad state.

1

To be a pure function, providing the same parameters must give the same result every time.

Each time we call Today(), we are providing it the same parameters (none), and yet not necessarily getting the same result (Monday, Tuesday, etc.).

2
  • 4
    this seems to merely repeat point made and explained in a top answer that was posted about two years ago. Hardly worth bumping two years old question with content like that
    – gnat
    Feb 3, 2015 at 11:33
  • 1
    I'm not too familiar with how stackexchange works, but I figured that since this was in top questions that it had already been bumped. As far as making a repeat point goes, I remember reading on meta that it can be helpful to have multiple similar answers. I feel like mine is succinct and potentially helpful.
    – Zantier
    Feb 3, 2015 at 11:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.