Live data from Hacker News

A guide to closures in Rust

hashrust.com

81–90 of 102 posts

Re: A guide to closures in Rust

#81

Earlier quoted context omitted.

Closing over variables is the thing that makes it a closure. Otherwise, you just have an anonymous function. A closure is a function plus the captured environment. The difference is meaningful here. You have to allocate a closure (and deal with its lifetime and the lifetimes of the variables it references) but the anonymous function is just a pointer to static code in the binary. That's the entire difficulty with clo…

> You have to allocate a closure That's incorrect, a closure in Rust compiles down to a static function that takes its environment as an argument. None of that requires a heap allocation in the above code.

I didn't suggest a heap allocation; indeed, in C++ too you can have stack allocated closures. I mean that it's not simply a pointer to static code; there is an associated data structure.

Re: A guide to closures in Rust

#82

The content is interesting but the use of ligature really put me off guard at first, and I am very familiar with Rust. I cannot imagine it being good for beginners to grok its syntax. This has reminded me of https://news.ycombinator.com/item?id=35925821 recently reposted, which boils down to: > if you’re preparing your code for others to read—whether on screen or on paper—skip the ligatures.

Do you mean the arrows? As long as they are fixed-width -single or double- it's ok and even pretty, but if variable-width fonts in code is a no-no for me.

Re: A guide to closures in Rust

#83

Earlier quoted context omitted.

In some language all functions capture their environment, making that original statement more true than you make it out to be. Personally I think the term closure should be banned, because it only adds confusion. There are just functions, some named some anonymous, some capturing the environment, some not, some being disallowed by some constraints from the host language. The term closure cuts through this space in a…

> 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 d…

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.

Re: A guide to closures in Rust

#84

Earlier quoted context omitted.

What is machine-specific about i32? It's a signed 32-bit integer, regardless of the machine you're on.

Why not use i36 then?

Because that's not a type in Rust. I don't understand where you're going with this.

Re: A guide to closures in Rust

#85

Earlier quoted context omitted.

Why not use i36 then?

Because that's not a type in Rust. I don't understand where you're going with this.

Why isn't that a type in Rust? It's a signed 36 bit integer, regardless of the machine you are on.

Re: A guide to closures in Rust

#86

Earlier quoted context omitted.

In some language all functions capture their environment, making that original statement more true than you make it out to be. Personally I think the term closure should be banned, because it only adds confusion. There are just functions, some named some anonymous, some capturing the environment, some not, some being disallowed by some constraints from the host language. The term closure cuts through this space in a…

> 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 d…

> Functions do not capture environments.

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

Re: A guide to closures in Rust

#87

Earlier quoted context omitted.

> 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 d…

> 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.

Re: A guide to closures in Rust

#88

Earlier quoted context omitted.

> 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 a…

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).

Re: A guide to closures in Rust

#89

Earlier quoted context omitted.

Because that's not a type in Rust. I don't understand where you're going with this.

Why isn't that a type in Rust? It's a signed 36 bit integer, regardless of the machine you are on.

There are several crates which provide this type if you want it, such as ux and num_x

Re: A guide to closures in Rust

#90

Earlier quoted context omitted.

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 a…

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!
Post reply on HN