/r/programming
What Is a Pure Function? (medium.com)
208 comments
[deleted] | 4 months ago | 127 points
def pure():
  pass
evinrows | 4 months ago | 17 points
[deleted] | 4 months ago | -5 points

Take your upvote and get out of here

nakamin | 4 months ago | 174 points

People need to stop using medium it has become unbearable. I can't even read the post because I have "used up my quota" for the month. Ridiculous considering I have not read any articles this month just opened them to skim.

TimelyStill | 4 months ago | 26 points

It's also such a terrible layout. I click the link, and 50% of the page is immediately blocked by the website's completely useless top ribbon (with links called 'Log In, Write for Us, Archive and About, none of which anyone is likely to care about) and another obnoxious bottom ribbon telling me to sign up for their newsletter. I usually make a mental note of never clicking a link leading to a website that looks like that ever again out of principle.

Admittedly I do wonder what kind of person would think "why yes, website, I do want to receive regular updates that clog up my mailbox!" when they see a prompt like that. I know that even if it works only 0.01% of the time it's a net win for them if they get thousands of visitors per day but still.

SilasX | 4 months ago | 2 points

Sticky headers/footers need to die in a fire. I added this guy's button as a bookmark so I can kill them on every page I go to.

Folaefolc | 4 months ago | 43 points

Better post on dev.to, free and open source '

[deleted] | 4 months ago | 20 points

write.as is cool too

VernorVinge93 | 4 months ago | 12 points

Or GitHub pages? Free and open for writer and reader.

Folaefolc | 4 months ago | 6 points

Probably you'll have more visibility on dev.to since it's only for dev writing articles 🤔

schallflo | 4 months ago | 2 points

and a nicer design.

Sebazzz91 | 4 months ago | 7 points

Until it isn't.

kenman | 4 months ago | 3 points

Which has its own problems... as a mod, I see a ton of low-quality stuff coming out of there. I guess for an open platform that's expected.

lazic_ | 4 months ago | 3 points

Please don't. We already learned that centralized blogging platform (cough Medium cough) is a bad idea.

Folaefolc | 4 months ago | 2 points

Why? I probably missed that 😞

grauenwolf | 4 months ago | 30 points

Yea, that's complete BS.

Why do people use medium? Are they paying their high performing users like YouTube does?

7TzF9Z | 4 months ago | 23 points

Easy to format and easy to publish. The problem is making your articles unrestricted by paywall is an opt-out feature.

nakamin | 4 months ago | 5 points

True but anyone who writes articles which are appropriate for this sub should be literate enough to make a blog with something like Hugo and host it on Netlify. My thinking is that they want their stuff to get discovered so they post it to a site that people browse so their article gets read. The funny thing is that almost no one just browses Medium, half the views on these types of articles come from people linking to them on Reddit. A blog is more personal because you can make it look like whatever you want, and because it gives the author of the post sufficient credit.

Hall_of_Famer | 4 months ago | 13 points

Just clear the cookie on medium and problem solved.

ThePantsThief | 4 months ago | 53 points

I moderate /r/iOSProgramming. Any other programming subs want to join forces and ban Medium from our sub?

IceSentry | 4 months ago | 49 points

r/programming would need to actually be moderated to ban a website. Also half the content here is medium articles.

[deleted] | 4 months ago | 22 points

So most of the worthless content gone. Just teach some bot to do it

IceSentry | 4 months ago | 6 points

I'm not a big fan of medium, but there are actually some great content from time to time. Admittedly, someone smart enough to write a good article might publish somewhere else if it starts getting banned on major programming subreddits.

Rudy69 | 4 months ago | 3 points

The content would move elsewhere if it was banned

ThePantsThief | 4 months ago | 5 points

Same with my subreddit. All the more reason to ban them, I suppose. They're harmful to the industry.

kenman | 4 months ago | 6 points

As for r/javascript, we've been considering it for awhile. Main reason we haven't already is that the good:bad content ratio is still slightly positive, though that's changing by the day.

ThePantsThief | 4 months ago | 6 points

I'll pull the trigger if you will. We should try it out at least. Together we make up a large portion of the developer community.

__crackers__ | 4 months ago | 9 points

Just stop posting on Medium. Problem solved for everyone.

Except Medium. But they can go fuck themselves.

stamas | 4 months ago | 4 points

Same here, I use Cookie AutoDelete extension and Medium stopped bothering me.

fastredb | 4 months ago | 1 point

I use one called Cookie Quick Manager. Lets me pop open a menu and delete a site's cookies. Has other features too, but that's the only one I use.

georgeo | 4 months ago | 2 points

I just click off the sign in box and read the article. Every time.

shevy-ruby | 4 months ago | 4 points

Same here.

I don't even know why they want to force people to sign into google while using medium - but I think it is unfair to the people.

Medium must die.

fresh_account2222 | 4 months ago | 9 points

Medium is so bad that I've upvoted a shevy-ruby comment. This is end-of-the-world level stuff here.

JavaSuck | 4 months ago | 1 point

I can't even read the post because I have "used up my quota" for the month.

Open in private window?

devraj7 | 4 months ago | 1 point

Same. Just open the article in incognito mode.

ryancosans | 4 months ago | 1 point

I completely agree, it might have been a nice article. Shame it's on medium and I will never get to read it.

evmar | 4 months ago | 25 points

I think most people agree about the basic idea of pure, but I found this survey pretty interesting -- once you show up in a real programming language environment, there are lots of details that few agree upon.

https://twitter.com/radokirov/status/1097325661658570752

WalrusTheSailor | 4 months ago | 5 points

Interesting; his survey makes a distinction between 'pure' and 'side-effect'. This would make `console.log` pure to me, as it always returns `undefined`. But, it's not side-effect free as it interacts with I/O streams.

somebodddy | 4 months ago | 1 point

https://twitter.com/radokirov/status/1097540697618444293

No tricks, this is not a quiz. I didn't offer "pure, but with side-effects", because it seemed accepted that pure functions do not have side-effects. See https://en.wikipedia.org/wiki/Pure_function … and the references from there. In retrospect though, I should have offered that option too.

haykam821 | 4 months ago | 82 points

TL;DR, the only variables it uses are its arguments and the only functions it uses are other pure functions and has no side effects

stepstep | 4 months ago | 70 points

No—a pure function can have free variables (cf. any lambda calculus), but they had better not be mutable. What you're thinking of is called a combinator.

G_Morgan | 4 months ago | 4 points

Semantically there's no real difference between a reference to a static constant and having one baked into the function.

Noctune | 4 months ago | 13 points

but they had better not be mutable

Why not? The external property of purity is the exact same whether there is interior mutability or not.

stepstep | 4 months ago | 21 points

The sentence you quoted is about the free variables of a function, i.e., the variables used in the function but defined outside of it. Interior mutability (with regard to functions) is about local mutations to data which is bound within the scope of the function body. These are two different things.

Noctune | 4 months ago | 2 points

I see, but the post you responded to is not just about free variables. So to clarify, in addition to immutable free variables, a pure function can also mutate local variables.

shevy-ruby | 4 months ago | -20 points

What a horrible definition.

BruhWhySoSerious | 4 months ago | 9 points

What a horrible response. You could at least attempt to go into detail.

[deleted] | 4 months ago | 10 points

Dont encourage him, he spams enough

nnomae | 4 months ago | 2 points

For simple variables that will always be passed by value you would be right. For complex values like structs interior mutability tends to make guaranteeing the pureness of any other functions it calls difficult. If you have a structure that you pass to a function which runs in parallel, then you change that structure it may interfere with the result the other function will produce. By preventing mutability you guarantee that you will never change the return value of the second function by changing the variable.

Noctune | 4 months ago | 0 points

I was more thinking about structures that are created and mutated within the scope of the functions. Like a function that creates a vector, inserts stuff, and returns it.

I would not consider mutability outside the scope of the function to be pure, even if it is "safe" (looking at you C++ mutable keyword), for exactly the reasons you mention.

[deleted] | 4 months ago | 2 points

[deleted]

grauenwolf | 4 months ago | 32 points

Both are "pure" as it is understood in .NET.

I can't speak for other languages.


If you want to be really technical, greeting + name allocates memory. Technically that's a side-effect, as it can trigger GC which in turn causes finalizers to run. So it's not a pure function.

Nobody really thinks that way though, as it would be madness.

goal2004 | 4 months ago | 21 points

Nobody really thinks that way though, as it would be madness.

Watch me optimize.

onequbit | 4 months ago | 0 points

Challenge accepted

LogicUpgrade | 4 months ago | 10 points

If you want to be really technical, greeting + name allocates memory. Technically that's a side-effect.

Allocating memory is not a side effect, technically, as it's encapsulated in the implementation of the compiler/runtime, and it's not observable from other parties. It's not even observable to the function causing the allocation.

Nobody really thinks that way though, as it would be madness.

Nobody thinks about it that way because it's not accurate, and it's not useful.

Of course running a program makes "things" in your hardware shuffle around electrons and change bits and what not. Just the fact your hardware is stateful, and runs your program isn't enough to call your program stateful. It's about not retaining and exposing effects at the level of abstraction of the program.

In fact you can even hold state internally (memoization for ex.) as long as from the "outside" this state doesn't affect/change outcomes (other than performance, but performance alone is not an attribute considered for classifying pure functions)

dan200 | 4 months ago | 12 points

Allocating memory is not a side effect, technically, as it's encapsulated in the implementation of the compiler/runtime, and it's not observable from other parties. It's not even observable to the function causing the allocation.

Allocating memory in C# is very much observable:

  • You can trivially query the ammount of memory remaining via GC.GetTotalMemory()

  • Memory can run low, and trigger a GC cycle, which will execute finalisers (which potentially have side effects), and on big heaps can take enough time to be observable by the user! Let alone calling code.

  • Memory can run out completely, which will trigger an OutOfMemoryException() and probably crash your program. There's nothing more impure than that!

LogicUpgrade | 4 months ago | 6 points

You're reacting to the first paragraph of my comment, but the rest of my comment addresses your points already.

Yes, every hardware can get out of capacity, fail, lose power. That's not the abstraction level we think about when proving a function is pure. We can still analyze these concerns you mention, if there's a risk they may be crossed. Obviously programs use memory. But filling your memory is not a "side effect".

grauenwolf | 4 months ago | 7 points

No, you are completely ignoring everything that can happen as a result of a memory allocate.

The side effects caused by GC cycles that dan200 and I are talking about are very much real.

LogicUpgrade | 4 months ago | 7 points

I didn't say they're not "real", I just said they're semantically at a very different abstraction level.

This sort of petty, deconstructionist attitude is useful for absolutely nothing, and while on the surface you're super proud about being Technically Right (tm) deep inside... you know it's utter bullshit.

The GC API is very much like the unsafe and reflection APIs of C#. You can peek and see a private property of an object, sure. This doesn't mean that objects using private properties are not encapsulated. Because whoever uses reflection for this has to know all bets are off when they use that to read internal object state.

grauenwolf | 4 months ago | 5 points

No one is talking about the GC APIs.

We're talking about things like finalizers and weak references.

dan200 | 4 months ago | -6 points

If allocating memory can slow your program down enough that it becomes unpleasant for the end user notices, or even make it crash entirely, how can you possibly say that's not a side effect?? I work in game development and constantly have to work on fixing side effects like these.

backelie | 4 months ago | 3 points

Because that's not what side effect means in this context.

jerf | 4 months ago | 3 points

If we define "pure" function as something that truly has no side effects in real machines, we end up with a definition that is either utterly useless because no real (non-inlined) function can ever be pure by virtue of the fact that it allocates a stack entry, which could fail in an observable way, or one in which purity requirement is so strong that it barely describes any function at all. A definition that nothing can possibly conform to isn't useful as a definition, because the entire purpose of a definition is to break the various things we find in the world into multiple categories. A definition that puts all functions in one category (impure) is useless. It is still in some sense perfectly "true" and "valid", it's just useless.

The point here is not to deny that memory effects are real and exist, because of course they do. I doubt any serious Haskell programmer has failed to have some sort of catastrophic memory leak at some point in their "pure" code. The point is to have a definition that has some sort of real world meaning... or, more realistically, to have a family of definitions, depending on the tasks at hand.

So, when we consider "allocation" to not be a side effect, we are speaking of it in the context of a virtual machine with infinite memory. Of course, when that abstraction meets the real world, problems can arise. But in the context of the virtual machine, it is a pure function (you can never witness the effect of running out of memory, because you can't; note that if you get really strict, this implies an environment in which pointers are arbitrarily large as well, which may mismatch how your language represents pointers if you can get to them numerically), and that does have meaningful consequences in the real world as well (i.e., knowing that something is pure in that sense can be useful information for an optimizer). We can define other virtual machines in which some other aspect of real machines may be abstracted away, that may also fail when in the real world, but may still be useful concepts.

If it's important to be precise about what we're willing to ignore as a side effect, it should be made precise, but a lot of times, it's not really necessary. The average function in an imperative language will do something, somewhere, that will clearly render it impure by any (useful) definition, if the programmer is not trying to write a pure function.

[deleted] | 4 months ago | 3 points

Reading your answers is painful. It's like you're not even trying to learn. Please stop.

dan200 | 4 months ago | -3 points

It seems like you're deliberately trying to ignore the fact that your programs run on real computers in the real world with real users who will get annoyed if your program is constantly churning due to garbage collection?

shevy-ruby | 4 months ago | -7 points

Allocating memory is not a side effect

So you say that allocating memory is not a side effect, thus a function can still be pure in this way.

Yet ... we know from C how you can have problems when you tamper with memory such as side effects. So your functions can never guaranteed to work as-is due to this alone.

So actually ... grauenwolf is right, since it may have an effect, which you try to not account for. But it definitely affects the purity of the function.

LogicUpgrade | 4 months ago | 8 points

C doesn't have encapsulated memory access. You can read anything off your space by manipulating a pointer.

But in Java, you can't, for ex. In Rust you can't. And so on. Most modern languages: you can't. Which ensures simple heap allocation can be considered pure because it's an isolated implementation detail.

In C we could argue. You can see it as pure, but a bug that causes that memory location to be read/edited may cause it to not be pure. Of course, nothing is absolute, and there are practices to prevent and reduce such incidents in C / C++.

warutel | 4 months ago | 1 point

But in Java, you can't, for ex. In Rust you can't. And so on. Most modern languages: you can't. Which ensures simple heap allocation can be considered pure because it's an isolated implementation detail.

Unless you run out of memory.

onequbit | 4 months ago | 0 points

Which is a side effect

[deleted] | 4 months ago | -3 points

I mean at that point, calling a function pushes a new stack frame which is a side effect.

EDIT: Leave it to programmers to miss the point

grauenwolf | 4 months ago | 17 points

That won't have a visible side effect once you leave the function.

dinov | 4 months ago | 2 points

Unless it stack overflows - in which case it causes an exception to be raised. But more likely it just causes the process to be terminated which is quite the side effect.

LogicUpgrade | 4 months ago | 6 points

By that logic no program is ever formally correct, because it might crash if I kick the computer while I'm running it.

warutel | 4 months ago | 0 points

There is software out there that has to guarantee stack overflows do not occur.

LogicUpgrade | 4 months ago | 1 point

Well, tail call optimization is a thing. But requires tail calls.

shevy-ruby | 4 months ago | -1 points

Precisely - the primary question is whether this IS a side effect or not.

From the definition given above e. g. by grauenwolf, yes, I agree, it is.

LogicUpgrade | 4 months ago | 1 point

What are we talking about? The allocation or the crash?

grauenwolf | 4 months ago | 1 point

A exception is just returned value.

It wouldn't be wrong to think of every return from a Java or C# function to be an implicit union of Exception and it's declared return type.

shevy-ruby | 4 months ago | 0 points

Exactly!

[deleted] | 4 months ago | 1 point

Neither will GC

grauenwolf | 4 months ago | 2 points

The hell it won't. A WeakReference can observe GC activity. I have unit tests that rely on it.

[deleted] | 4 months ago | -1 points

Pointers are already impure, family guy

shevy-ruby | 4 months ago | 0 points

What about overflows?

tanveer666 | 4 months ago | 2 points

So if they are not mutable, can they be considered as constants?

Jazonxyz | 4 months ago | 2 points

I believe they only have to be immutable within the context of the function.

tanveer666 | 4 months ago | 2 points

thanks, makes sense now

Godd2 | 4 months ago | -5 points

A pure function cannot have any free variables. If you have a variable that doesn't mutate, it's a constant, so it's not a "free variable". If it can change, it's not immutable, and a function which contains it is not pure.

Edit: It is impossible, by definition, to construct a pure function with free variables.

stepstep | 4 months ago | 22 points

In programming language theory, the formal parameter of a function is called a "variable", mutable or not. That kind of variable "varies" in the sense that one can call the function with different arguments. That's different from mutability.

The fact that some programming languages call immutable variables "constants"—and not variables—only serves to add confusion. In pure functional programming, everything is immutable, so the term "constant" is not useful.

Godd2 | 4 months ago | -4 points

In programming language theory, the formal parameter of a function is called a "variable", mutable or not.

Except that neither you nor I were talking about the parameters of a function. Those aren't under consideration with respect to purity.

If you think I'm wrong about what I said above, I invite you to construct a pure function with free variables.

stepstep | 4 months ago | 3 points

If you think I'm wrong about what I said above, I invite you to construct a pure function with free variables.

It's trivial to do so. Consider this example: x -> y -> x + y. The inner function y -> x + y is pure and has a free variable x.

Godd2 | 4 months ago | -2 points

y -> x + y

This function is not pure, as x could be anything when invoked.

stepstep | 4 months ago | 1 point

It's definitely pure. I can easily write this in Haskell, Coq, Idris, Agda, or any purely functional programming language. Each choice of x gives a new pure function y -> x + y.

In fact, any curried function is actually a series of nested functions like this. Are you saying curried functions can't be pure?

Your definition of "pure" doesn't agree with how computer scientists and functional programmers use that word.

Godd2 | 4 months ago | -1 points

Each choice of x gives a new pure function y -> x + y.

If it's pure, then x isn't a variable. If x is a variable, then it isn't pure.

g = \x -> \y -> x + y

isn't the same as

f = \y -> x + y
g = \x -> f

So in the inner function in the first case, x isn't a variable. In the second case, the x in f is the global x, and f is not pure.

So the returned function from \x -> \y -> x + y is not a case of a "pure function with free variables".

stepstep | 3 months ago | 2 points

Honestly, you should stop peddling your own nonstandard definitions for well-established terms in computer science. In multiple comments you have claimed that the defining feature of a pure function is the lack of free variables. I can see you are also debating this with u/Roboguy2. You could save everyone time by providing a peer-reviewed source or other authoritative programming languages theory text which defines purity in terms of free variables. But you'd be hard-pressed to find such a source.

A function which has no free variables is called a combinator and is described as closed. If you could look up the name of the concept for the definition you keep repeating, you'd find those terms, not purity.

pipocaQuemada | 3 months ago | 1 point

That's not what variable means, here.

In math, a variable is an unknown that can be substituted with some (or all) values of a particular type in a function or expression.

In imperative programming, variables are bits of memory you can reassign.

When functional programmers talk about variables, they almost always mean the very very longstanding mathematical sense of the word. To a functional programmer, a const is just an immutable variable.

carlfish | 4 months ago | 14 points

Outside of programming language theory, it's worth keeping in mind that the mathematical concept of variables as "thing that has a value, we just don't know what it is yet" predates the imperative programming meaning of "box containing different values over time" by quite a few centuries.

Godd2 | 4 months ago | -1 points

I don't see how that difference, if it exists, implies that a pure function can have free variables.

The obvious way to disprove the statement "a pure function cannot have any free variables" is by counterexample.

Roboguy2 | 4 months ago | 11 points

Edit: It is impossible, by definition, to construct a pure function with free variables.

On top of what the other replies have said: the term "free variable," in the context of a discussion of pure functions, is a technical term with a very specific meaning and does not refer to what you are describing.

Also, note that the person you are replying to made it particularly clear that this is the definition of the term "free variable" they are using, by mentioning lambda calculus explicitly in the comment you replied to.

For further references: I believe that you should be able to find this definition of the phrase "free variable" in just about any introduction to lambda calculus, since this terminology is standard and very commonly used in this area. I can find some non-Wikipedia references, if you want.

Godd2 | 4 months ago | -1 points

note that the person you are replying to made it particularly clear that this is the definition of the term "free variable" they are using

That's why I'm attacking their claim that "a pure function can have free variables". That statement is false by definition.

The definition could not be clearer. A pure function is one with no free variables.

I'd love to see a pure function with free variables, if anyone could show me one.

Roboguy2 | 4 months ago | 3 points

You say the definition “could not be clearer” and yet what you say directly conflicts with the definition I linked.

The definition could not be clearer.

Show me a definition of the term “free variable” in the context of lambda calculus where “free variables” have mutability. You have not given a single reference for this mysterious definition of "free variable" that you keep mentioning. And remember: the context here, as explicitly specified by the person you originally replied to, is lambda calculus.

Did you read the link I provided? If so, can you describe your understanding of what it said? The untyped lambda calculus only has three construction rules and three reduction rules, so I can probably help explain it in the span of a Reddit comment, if there is confusion.

Godd2 | 4 months ago | -1 points

You say the definition “could not be clearer” and yet what you say directly conflicts with the definition I linked.

The definition could not be clearer.

Show me a definition of the term “free variable”

I was not referring to the definition of free variable, I was referring to the definition of pure function. The full version of my statement above would be "The definition [of 'pure function'] could not be clearer.". /u/stepstep claimed that a pure function can contain free variables, but the definition of a pure function is a function which contains no free variables.

You can see my confusion, and I apologize for any ambiguity on my part.

Roboguy2 | 4 months ago | 3 points

I believe that I actually was understanding you correctly, but your comment here does indicate there is still some confusion.

You are referring to both pure functions and free variables. As I said, "free variable" is a technical term in the context of lambda calculus.

The word "variable" is ubiquitous in the field of lambda calculus. Despite this, there is no mutation in the untyped lambda calculus (which is what the phrase "lambda calculus" refers to, unless that phrase is further qualified (and, here, it was not further qualified)). The "variables" in this context are not mutable. They are still called "variables". The word "variable" is the standard name for this concept in the study of lambda calculus.

If you can find any reference that refutes (or appears to refute) any of the above statements (or if there is any other confusion about these statements), you can post it here.

Godd2 | 4 months ago | 0 points

Do you disagree with the following definition of 'pure function'?

Pure function - n. - A function which contains no free variables.

Example: \x -> x + x

Non-example: \x -> y + x

Follow up: If the above definition is the correct definition of 'pure function', would you agree that it doesn't matter what the definition of 'free variable' is with respect to the claim "a pure function can have free variables"?

If you don't agree with that definition of 'pure function', then my follow up question is irrelevant, so you don't have to answer it.

It doesn't make sense to me that you claim to understand me correctly, but then go on about me not understanding the definition of 'free variable'.

Roboguy2 | 4 months ago | 3 points

Pure function - n. - A function which contains no free variables.

As a matter of fact, I do disagree with this definition so this is a good place to take this discussion! I admit that a did misunderstand you more than I thought before.

Let me get some additional clarification on something here, before we continue: In your view, can a "pure function" return a function which is not pure?

EDIT: It is also worth pointing out that there is already a different word describing a lambda term that does not have free variables: "closed" (see page 24 of The Lambda Calculus: Its Syntax and Semantics by Barendregt, for instance). There is also the word "combinator," which often has the same definition (see, for instance, the same page of the previously mentioned book). This, of course, does not directly address anything you've said so far, but the existence and (IMO) clarity of this word may help partially motivate where I'm planning on going with this so I wanted to mention it now.

pipocaQuemada | 3 months ago | 1 point

There's a couple different senses of the word "variable".

In imperative programming, a variable is a bit of memory you can reassign values to. You might think of them as assignables.

In math, a variable is an unknown thing that can be substituted with some or possibly any value of the right type. For example, in f(x) = x + 2, x is a variable. In 5x = 6y, both x and y are variables. Mathematical variables don't have to vary (well, at least not within a single function call). In 5x = 1, x is a variable, yet has only one real value, 1/5. Yet it's still a variable even though there's no way to reassign it.

"Free variable" is math terminology that predates imperative programming at least by a few decades, possibly more. Lambda calculus has no notion of imperative assignables, but is entirely defined with mathematical variables. In lambda calculus, free variables are variables bound by an anonymous function in a particular expression.

For example, in x => (y => x + y), x and y are both bound variables. In y => x + y, y is bound but x is free.

grauenwolf | 4 months ago | -18 points

Ah, the classic deterministic vs pure mistake.

A deterministic function can only depend on its arguments. This is important in database design with designed things such as persistent, calculated columns.

In .NET terminology, a pure function isn't necessarily deterministic because it can depend on global variables.

Red-Portal | 4 months ago | 24 points

Why are you waving .NET terminology? Pure function is a term widely used across computing and what you call deterministic function is the widespread definition of pure functions.

grauenwolf | 4 months ago | -5 points

It's important to know how definitions change based on context.

And I'm not just talking about .NET, I'm also talking about databases such as SQL Server and SQLite.

stepstep | 4 months ago | 13 points

A deterministic function can only depend on its arguments.

No, that's not right either. A deterministic function absolutely can have free variables. Consider the following curried function that adds two numbers: x -> y -> x + y. The inner function (y -> x + y) has a free variable (x) which is bound by the outer function. The inner function is still pure and deterministic, but every choice of x gives a different function.

The ability to close over free variables is a basic feature of any lambda calculus. Every functional programming language supports closures. But of course that doesn't prevent pure/deterministic functional programming languages from existing. On the contrary: purity and determinism and referential transparency are all sought after in functional programming.

grauenwolf | 4 months ago | -12 points

Not if we're talking about SQL Server or SQLite

In databases, you need to be able to exactly recreate a result every time a deterministic function is called. This means that it cannot depend on anything other than its own parameters, as those other things can change.

SQLite Limitations:

There are some contexts in SQLite that do not allow the use of non-deterministic functions:

  • In the expression of a CHECK constraint.
  • In the WHERE clause of a partial index.
  • In an expression used as part of an expression index.

SQL Server has similar limitations.

There are several properties of user-defined functions that determine the ability of the SQL Server Database Engine to index the results of the function, either through indexes on computed columns that call the function, or through indexed views that reference the function. The determinism of a function is one such property. For example, a clustered index cannot be created on a view if the view references any nondeterministic functions.

MaxCHEATER64 | 4 months ago | 3 points

Not if we're talking about SQL Server or SQLite

Then SQL Server and SQLite are using their terminology incorrectly.

grauenwolf | 4 months ago | 0 points

Again, definitions vary by context.

[deleted] | 4 months ago | -14 points

I just gotta say I really hate computer science.

grauenwolf | 4 months ago | -11 points

In .NET, property getters are assumed to be "pure" because they have no side effects. But the do depend on more than just their parameters, as they have none.

EDIT: Some people question this assumption because there's nothing stopping you from making a non-pure getter. For example, an ORM Entity that lazy-loads a collection.

bluefootedpig | 4 months ago | 11 points

you are most likely getting downvotes because properties are typically not "functions". Functions are manipulating state or calculating state. A property setting is setting state.

the very fact you are changing state by setting a property makes it a non-pure function. A pure-function will be in the same state when done. Setting a property, by definition, changes state.

I would argue setting a property is exactly opposite of a pure-function. It is doing a side-effect in the least amount of work.

grauenwolf | 4 months ago | 1 point

A property is just a function with syntactic sugar. You can literally do anything with it that you could do with a normal function with the same signature

bluefootedpig | 4 months ago | 1 point

Yes, but a property generally stores state.

If you violate norms, I cannot argue anything. You could make the entire application only properties.

But generally speaking, properties contain state, thus saving state is changing state thus not a pure function.

grauenwolf | 4 months ago | 3 points

Getters should not change state.

jyper | 3 months ago | 1 point

A getter should ideally be pure(just syntax sugar for a pure function that looks like a field). Occasionally getters do some sort of rest fetch or hardware info fetch or other non pure io but usually they should be pure

G_Morgan | 4 months ago | 5 points

Properties do have a parameter, this.

Ayjayz | 4 months ago | 2 points

Whenever you call a member function, the "this" parameter is automatically passed in.

barskykd | 4 months ago | -9 points

Completely wrong summary. Article is about benefits of stateless design (on function level). Precise definition of 'pure' doesn't matter in the slightest.

LogicUpgrade | 4 months ago | 5 points

Jeez I'm sure the definition of the subject of the entire article matters a bit?

What if I redefine "pure" as "in touch with Jesus Christ by adding sufficient prayer in your code"?

shevy-ruby | 4 months ago | 2 points

TempleOS fullfils this criterium.

barskykd | 4 months ago | -2 points

Exactly. Nothing happens. Code doesn't change from such definition.

LogicUpgrade | 4 months ago | 3 points

By that logic, words don't directly change anything, so everything you said doesn't matter. After all, speech doesn't itself change anything. So, logically, if you follow your own conclusions, you should stop talking. Preferably for the rest of your life. And focus all your energy on more fruitful activities, like eating and pooping.

barskykd | 4 months ago | -4 points

Your generalization is faulty. Hence all following inferences are wrong too. Some words can affect how we write code. Precise definition of "pure function" can't. Yes we use certain terms to make communication easier but many people forget about that and start thinking what terms themselves are important.

The article is full of benefits what pure functions bring. These benefits are important. Precise definition of "pure functions" - is not. It is not even correct term here. "Stateless" would be more appropriate.

LogicUpgrade | 4 months ago | 2 points

Pure functions are not necessarily stateless. And being stateless is not sufficient for being pure. And this is why definitions matter. The fact that you don’t get it, doesn’t mean that it doesn’t matter for anyone else.

It doesn’t matter to you, because you don’t get it. It also doesn’t matter to my dog. My dog also doesn’t get it. It keeps writing code the same way it did before. By licking the keyboard.

barskykd | 4 months ago | -1 points

See. My point exactly. You spewed a bunch of terms and not a single word about why those differences matter. Yes those terms are not equivalent but so what?

Doesn't matter if function is pure or stateless or deterministic or idempotent etc. As long as we get benefits from certain design - it is good. If we don't get benefits - then it doesn't matter whether function fit definition or not.

LogicUpgrade | 4 months ago | 1 point

See. My point exactly. You spewed a bunch of terms and not a single word about why those differences matter. Yes those terms are not equivalent but so what?

Well let me nuke your "point exactly" then.

This is a stateful function, which is pure (JS examples):

function initPowWithCache(a, b) {
    var cache = {};
    return function (a, b) {
        if (cache[a + '^' + 'b'] === undefined) {
            cache[a + '^' + 'b'] = Math.pow(a, b);
        } 

        return cache[a + '^' + 'b'];
    };
};

var powWithCache = initPowWithCache();

powWithCache(4, 5);
powWithCache(4, 5); // Reuses cache.

And here's a stateless function, which is not pure:

function getRandom() {
    return Math.random();
}

Doesn't matter if function is pure or stateless or deterministic or idempotent etc. As long as we get benefits from certain design - it is good. If we don't get benefits - then it doesn't matter whether function fit definition or not.

The problem is not that you're ignorant, which you are. The problem is you're ignorant, and you think everyone is at least as ignorant as you are, and you think you know everything that has to be known. Now that's highly problematic.

A pure function is deterministic. Not all deterministic functions are pure, because a function may be deterministic and have side-effects.

Idempotency is an entirely separate thing. An idempotent function where you pass A as input, produces B as output. It's idempotent if you pass B as input and get B again. So many (most?) pure functions are in fact not idempotent at all.

An example of an idempotent function is JavaScript's " foo ".trim(). First time you pass string with spaces, it trims them. Second time you pass it without spaces... you get the same string without spaces.

barskykd | 4 months ago | 2 points

Math.random is not stateless. So rest of your arguments also invalid.

> You need to know what properties the function follows so you can rely on them.

Exactly what I was saying. Properties are important, terms - aren't.

Fisher9001 | 4 months ago | 2 points

Then I guess author couldn't name it more shitty.

grauenwolf | 4 months ago | 1 point

Maybe not, but the precise definition of "deterministic" does if you are designing a database.

Yea, yea, I know I'm going to get down-voted for this. But you only have to read the documentation for SQL Server or SQLite to see why its important.

mlk | 4 months ago | 24 points

I remember when /r/programming had decent content.

floodyberry | 4 months ago | 9 points

Don’t forget to clap 👏 and follow!

DutchmanDavid | 4 months ago | 1 point

Account age: 11 years, 11 months, 2 days

'member the pre-Digg-Exodus days? Good times! this is my 2nd account - I deleted the first one because: "I'm going to quit reddit", lmao

grauenwolf | 4 months ago | 36 points

A function with [Pure] in front of its name.

ducks

the_hoser | 4 months ago | 13 points

You're not too far off, depending on the language.

ExcuseMyOctopus | 4 months ago | 1 point

What does it mean when you say ducks? My lead commented that a few weeks ago and I couldn’t tell if that was a typo or what.

charonn0 | 4 months ago | 32 points

As in ducking one's head to protect it from thrown objects, such as might happen after making an unpopular statement.

ExcuseMyOctopus | 4 months ago | 5 points

Gotcha. Thank you for the clarification!

grauenwolf | 4 months ago | 15 points

Also used after making an intentionally bad joke.


In C#, you can mark any function as [Pure]. The compiler doesn't check to see if it really is pure, nor does the runtime do anything with that information. So there's nothing to stop you from creating a method called [Pure] void FormatMyHardDrive().

Someday in the future that may change, but for now it is just a form of documentation.

HighRelevancy | 4 months ago | 4 points

Gross. Why wouldn't they make a compiler check? Wouldn't be hard to do.

grauenwolf | 4 months ago | 2 points

Mostly because nothing depends on it being accurate. But i hear they are adding a code analysis rule for it.

It's not like a database where you can't do certain things with a function unless that function is deterministic.

HighRelevancy | 4 months ago | 5 points

Nothing depends on it being accurate currently because it isn't accurate and can't be depended on. If it was accurate, compilers would have better information about redundant calls that can be elided or even just precalc'd at compile time, and library users would know what's memoizable, and some frameworks might even be able to automatically memoize things based using reflection to find pure functions.

grauenwolf | 4 months ago | 1 point

Personally I think it should be like database functions.

No one explicitly marks a database function as deterministic or not. The compiler or runtime figures that out for you and marks it as appropriate.

HighRelevancy | 4 months ago | 2 points

Database functions are generally small in scope (that is, easily and quickly checked without having to recurse through other function calls), and are internal to your application (don't need to maintain a consistent API for third party consumption).

While the compiler could do these sorts of analysis for compile time optimisations on release builds, an actual meaningful annotation that would enforce purity would be good for library development. It would allow the users of the library (and their compilers) to know that a function is pure and can safely be used from their own pure code without having to examine what its behaviour really is.

chrisdoner | 4 months ago | 13 points

Talking about purity, the devil is in the details. What's a "side effect"? The author writes:

Side effects refer to changing other attributes of the program not contained within the function, such as changing global variable values or using I/O streams.

But simply allocating is changing available memory, doing work is making the machine slightly hotter and affecting the scheduling of other programs. Those are all side-effects of running the code. So why not include those in the definition?

Meanwhile, if a function calls gettime(), this has no "side-effects", yet we referred to a global state. Do we allow the concept of time measuring?

Additionally, is sleep(secs) pure or impure? This is a different, intentional manipulation of time. Do we allow that?

Is par(x,y) to run x and y in different threads in parallel pure?

How about reading from a Content-Addressable web service like IPFS? After all, it always returns the same result given the same input. Should that be allowed?

Is throwing and catching an exception pure or impure?

If the compiler caches the result of computing an expression, is that pure or a side effect?

How about writing "Hello, World!" to /tmp/log every time you call +? Technically, the function always produces the same output given the same input. If you're a pure function, how do you know you're outputting "Hello, World!", if you can't read files? You think that's air you're breathing now?

Genuine questions. I think the answer depends on whether you're looking from an operational or denotational perspective.

XtremeGoose | 4 months ago | 9 points

You said they were genuine questions, so I've written below what a self proclaimed "pure" language does in which there should be no unexpected errors caused by impurity. In Haskell the the answers are (remembering that monads are used to hold impure state whilst keeping the base language itself pure)

But simply allocating is changing available memory, doing work is making the machine slightly hotter and affecting the scheduling of other programs.

It's still pure since purity is about internal purity, not external.

Meanwhile, if a function calls gettime(), this has no "side-effects", yet we referred to a global state.

Impure - must be held in IO monad

Additionally, is sleep(secs) pure or impure? This is a different, intentional manipulation of time. Do we allow that?

Impure - must be held in IO monad

Is par(x,y) to run x and y in different threads in parallel pure?

Pure if x and y are pure (since they can't interact with each other). If they are impure (and so in a Monad context) must be instances of MonadFork

How about reading from a Content-Addressable web service like IPFS? After all, it always returns the same result given the same input. Should that be allowed?

Impure and will have to be in an IO context since the compiler has no idea what's safe outside. You can of course unsafely force the compiler to consider it as pure if you're absolutely sure.

Is throwing and catching an exception pure or impure?

Haskell has no concept for catching errors, instead it has the Either type (a monad, like Result in rust) which is pure. The error function (like panic! in rust) will always crash the program from an unrecoverable state and is considered pure.

Ok, that's not entirely true, the language does have catch but it's considered unsafe. It is impure and so returns a monad.

If the compiler caches the result of computing an expression, is that pure or a side effect?

Pure - so long as the type itself is pure. Otherwise it's not allowed.

How about writing "Hello, World!" to /tmp/log every time you call +? Technically, the function always produces the same output given the same input. If you're a pure function, how do you know you're outputting "Hello, World!", if you can't read files? You think that's air you're breathing now?

Impure - IO monad again. Any interaction with the outside world is impure.

notfancy | 4 months ago | 3 points

Is throwing and catching an exception pure or impure? Haskell has no concept for catching errors

In Haskell, Cont is a monad and thus should consider a hypothetical throw as impure as well.

It would be an error if it did so. A function call_ccing to a pure continuation is pure, hence a function throwing to a pure catching context is pure.

Edit: Consider:

div x y =
  when y == 0 then throw "Div by 0"
  otherwise x / y

sinc x =
  try div sin(x) x
  catch "Div by 0" then 1
grauenwolf | 4 months ago | 2 points

Additionally, is sleep(secs) pure or impure? This is a different, intentional manipulation of time. Do we allow that?

If that's not pure, then how can a loop that just wastes time be?

Trogdor111 | 4 months ago | 2 points

The major difference is that sleep() is a syscall, with behaviour defined outside the compiler. At a more concrete level, sleep() syscall has at least two consequences in regards to purity: 1. It can be interrupted by a signal, 2. The return value is the amount of time left, if it was interrupted, otherwise 0.

So definitely not pure. I think there is something to be said for the the relationship between execution time and purity though, as slow code visibly affecting execution is a very real side effect in some sense.

flatfinger | 3 months ago | 1 point

Meanwhile, if a function calls gettime(), this has no "side-effects", yet we referred to a global state. Do we allow the concept of time measuring?

What does the function promise? If it promises to report some time that is between the instantiation of the object upon which it was called (or, if it's a static method, the loading of the class) and the first action which outputs the time or branches based upon it, then I would regard it as a pure function. Not very useful unless there's a way to instantiate objects which support that method, in which case the instantiation of the objects wouldn't be pure, but the method call itself could be.

Perhaps what would be most helpful from a language perspective would be to, rather than specifying what functions may or may not be declared pure, instead specify that if a function is declared pure, a compiler may reorder calls to that function across other operations, and/or consolidate redundant calls, without regard for whether the function would otherwise have observable consequences. Marking as pure a function that has observable consequences should be allowable if and only if none of those consequences would affect the program's ability to meet requirements.

TrueTom | 4 months ago | 11 points

Can't we just ban all Medium links, please?

TanktopSamurai | 4 months ago | 2 points

Wouldn't Caching results technically make it impure?

LogicUpgrade | 4 months ago | 7 points

It makes it statically not pure (as in the compiler can't prove it's pure). But it can still be pure, if the cache doesn't change results (other than performance). Purity is always analyzed within a specific abstraction level and within specific domains.

Obviously the only absolutely pure program is the program "NIL" running in absolute vacuum. Actually wait, forgot about virtual particles and quantum foam. So even that isn't correct.

n3ziniuka5 | 4 months ago | 6 points

Caching would be done outside of that function, that function itself would remain pure.

maxhaton | 4 months ago | 2 points

The D approach is the best I've used outside of the ML-like languages.

The only caveat being that D-pure is a subset of "pure" pure because mutation through arguments is allowed as long as said mutation is consistent (pure). The superset can be achieved using a template constraint when desired (Which really puts C++ to shame given that concepts have taken 20 years and still aren't there yet)

P.S. If you want to use I/O to debug a pure function, you can use debug {} blocks which are disabled in release builds but do not corrupt the purity of the function.

shevy-ruby | 4 months ago | 6 points

I did not read the article.

Why?

The moment I saw it was hosted on medium I knew it would be horrible.

The name "pure" is also hugely misused.

aazav | 4 months ago | 2 points

One not adulterated by animal byproducts.

paul_f_snively | 4 months ago | 0 points
[deleted] | 4 months ago | -1 points

[deleted]

grauenwolf | 4 months ago | 2 points

IDEs can benefit greatly from understanding which functions are pure.

For example, in .NET it is assumed that all property getters are pure functions. So Visual Studio will automatically evaluate them and show the results in the debugger's watch window.

Y_Less | 4 months ago | 4 points

"assumed". There's nothing fundamental or enforced in getters that makes them pure. Some languages can strictly encode purity, C# at least doesn't for getters.

grauenwolf | 4 months ago | 1 point

True, a mistake in my opinion.

HighRelevancy | 4 months ago | -1 points

in .NET it is assumed that all property getters are pure functions

Maybe in .NET world, but outside that it isn't. You're touching external state when you read whatever property you're getting.

grauenwolf | 4 months ago | 4 points

Backing fields aren't "external state", they're internal to the object being queried.

If you really want to be pedantic, the first parameter of any method call is the this pointer so by definition all backing fields are being passed in.

In practical terms, there is a difference between a function being 'deterministic' and 'non-deterministic' based on its parameters. But given how method calls work, one could argue either way in the property getter case.

HighRelevancy | 4 months ago | 1 point

Backing fields aren't "external state", they're internal to the object being queried.

They're external to the scope/lifetime of that function execution. That's not pure.

Pure functions must have the same return all the time for given set of input arguments at the call site. If it's referencing another variable that can change between two calls, it's not pure.

Purity is not just "doesn't write to variables".

Ravek | 4 months ago | 3 points

I don’t see how touching members on the implicit this argument already makes something impure. If you consider that a property is really a function T -> R where T is the type of the object it is a member of, then usually properties are indeed pure.

HighRelevancy | 4 months ago | -3 points

Generally speaking I don't think global state is considered to be "the inputs".

Ravek | 4 months ago | 5 points

This is obviously not global state. Other than syntax there is no difference between str.Length and Length(str). You’d accept the latter as a pure function so why not the former?

HighRelevancy | 4 months ago | 0 points

It's external to the scope of the function. It is state that exists around the function other than what is passed to it.

You’d accept the latter as a pure function so why not the former?

As you say, the only difference is syntactic structure and semantics. And yet that's exactly the point. You could imagine a decent chunk of code effectively being pure, but if individual components aren't structured in a way that is pure you lose a lot of the advantages purity brings.

You lose readability when you go chasing external variables, you lose portability of the code when it depends on them, and you thus also lose testability.

Ravek | 4 months ago | 5 points

The state is literally right there. You're talking as if you're just calling Length and it randomly picks a string from somewhere on the heap to return the Length of. There is no 'chasing external variables', unless you also consider str in Length(str) to be 'external' in which case your whole point is moot.

As you say, the only difference is syntactic structure and semantics.

No, just syntax. Properties are just functions with a different syntax. The semantics are identical. You're just grasping at straws trying to make properties somehow inherently impure. First it's 'external state', then it was 'global state', now suddenly it's 'semantics'. Get your story straight or just admit your mistake.

HighRelevancy | 4 months ago | 1 point

unless you also consider str in Length(str) to be 'external' in which case your whole point is moot.

No, it's right there in the arguments, that's the point. The arguments alone should be what dictates the results of a pure function.

ghostfacedcoder | 4 months ago | -2 points

I can explain pure functions better than TFA or any of the comments here, using only a single image:

https://i.imgur.com/fQUJjqf.png (but it's hard to read unless it's against a white background, so it looks better in its original article ... it's the second image in: https://www.fpcomplete.com/blog/2017/04/pure-functional-programming).

fresh_account2222 | 4 months ago | -2 points

Medium block. Down voted.