Hacker News new | ask | show | jobs
by DonaldPShimoda 1119 days ago
> In some language all functions capture their environment

In some pieces of art all quadrilaterals are squares, but this doesn't mean the two terms are somehow equivalent and therefore one of the terms should be done away with.

There is a consistent technical distinction between "functions" and "closures".

> There are just functions, some named some anonymous, some capturing the environment, some not

No. Functions do not capture environments. Functions don't know what environments are. If you're talking about functions and environments together, you're talking about closures. That's really all there is to it.

2 comments

I agreed with your original comment but this insistence on "functions never capture environments" is not useful when a really large portion of programmers come from those kinids of languages and are trying to learn Rust.

You can insist on correct terminology or adapt to your surroundings and try to speak the language of your target audience. I assume somebody who calls closures "anonymous functions" is speaking as a JavaScript developer to JavaScript developers. Even if not, it's not unreasonable to adopt the terminology of such a popular language.

The "problem" with your perspective, as I see it, is that it is not I who is entering a context. Rather, it is other people who are trying to learn about programming language theory and design; they are entering my context. So it's not up to them what the terms mean, really. The terms have established meanings.

It is true that a lot of language communities conflate terms, and this is especially prevalent among the people who are hobbyists and amateurs in the space --- an important community, to be sure! But not a group of people who are already knowledgeable.

When people from the lay community of Language X choose to get involved in the community of Language Y or, more importantly, the community of programming languages research, they often encounter friction because suddenly these terms that they previously believed to be synonymous actually have very distinct technical meanings. So that is why I try to address these conflations when I see them.

That said, I do make a point to state up-front that my notes are pedantic, because I know not everybody cares to learn about such things, and that's perfectly fine! But I will continue writing corrections when I see them, though I try hard to make my corrections kind in nature.

> Functions do not capture environments.

They might not do that in Rust, they do in Haskell, JavaScript and plenty of others.

No, they do not. This is the technical distinction that I'm trying to get at.

A "function", in the academic literature, is a form that has two parts: a set of variables that it binds (called the parameters) and a bit of encapsulated functionality (called the body). The function itself has no knowledge of the outside world. This is why the notion of free variables is important, or even relevant. A free variable is any variable that occurs unbound within the body of a function. The function doesn't know anything about the free variables; they simply exist within it.

A "closure" is a pairing of a function with an environment. If you are talking about functions and "their" environments, you are talking about closures. In most languages, a function is only syntactically valid if all of its free variables are bound within the surrounding environment. (However, if you were to implement a language with dynamic scope instead of the now-standard lexical scope, you wouldn't even check such a thing statically.)

---

I'd like to try to make my point by drawing an analogy to another pair of PL terms that are often similarly conflated: "parameters" and "arguments".

A parameter is a variable that occurs in the binding context of a function definition, and is therefore considered to be bound within the body of the function. Parameters are not free variables.

An argument is a value that is passed to a function during a function call. Arguments are bound to parameters during the set-up of the function call.

Let's imagine I want to talk about an anonymous function `(λ (x) (add1 x))`. This is a function that has one parameter, `x`. It then returns the result of incrementing the value of `x` by 1 (we are assuming the value is a number).

If I had instead said that this function "takes one argument `x`", it would technically have been incorrect. When we're talking about the function, we know nothing about the arguments it will eventually take; we only have information about the parameters.

It is exceedingly common for people to use these terms interchangeably, but they are actually distinct in the academic literature, as they each refer to entirely separate (though related) things. The function/closure distinction is similar. Many people use the terms interchangeably, but they are actually meant to be separate. You are conflating them, and my comments here have been meant to educate people about the actual distinction.

The use of "takes" in "takes parameters" is probably not helping clarify your point here. (since functions "take/pass" arguments when called, but "have/make use of" parameters in their definition).
Good clarification; edited! I was too focused on the nouns and forgot that the verbs matter too. Cheers!
Haskell and JavaScript and the majority of humans call these things functions. That there exist a different context (a very specific academic context) where these terms have a slightly different technical meaning is completely irrelevant in the context of a normal user-level discussion on about programming languages.
I want to point out that I started the discussion by explicitly admitting up front that my point was pedantic in nature. It should have come as no surprise, then, that the point was... pedantic in nature.

The reason I feel this stuff is important to mention is because it is not uncommon to find discussions where the conflation does cause people headaches. The problem is exacerbated by the prevalence of people who claim that the difference is "irrelevant", up until the point that the difference actually matters, at which point those people are simply not around. There are a ton of small sets of terms of this nature that, when speaking to laypeople, you would think are just synonyms, except that it turns out that sometimes the technical distinction is important. It means people who actively seek out spaces to educate those who want to learn (like myself) have to do extra work to undo the faulty learning and then start over with correct definitions. Like you said: for most people it's not a big enough deal to worry about, but the distinction is present and there are times when it does matter.

I like informing people of things, and I happen to find interest in minute details, definitions of terms, and so on. I know that's not for everyone. To solve this "problem" (if I can call it that), I try to start my discussions by being honest about my intentions: I explicitly state that the point is minor or pedantic or something to that effect. That way I get to write about the things I want to write about while also giving people plenty of room to just choose not to worry about it if they don't care, and everybody comes out the other side happy. Except you, I guess. Sorry about that.