
Finding Closure in Rust - dbaupp
http://huonw.github.io/blog/2015/05/finding-closure-in-rust
======
Animats
It's good to see that. Rust's closure/lambda system has been in flux as
recently as a month ago.

Rust ties closures closely to lambdas, but that's not inherently necessary.
The article says _" Syntactically, a closure in Rust is an anonymous function
value defined a little like Ruby, with pipes: |arguments...| body."_ Actually,
that's a lambda, not a closure.

A lambda which references no variables from an outer scope is not a closure.

    
    
        |x| x*x
    

is a Rust lambda that isn't a closure.

On the other hand, a nested function in Python which references variables from
the outer function is a closure that isn't a lambda. That's also true in
Javascript. In Rust, you can nest functions, but you can't generate a closure
that way. A reference to the outer function scope in a Rust nested function
generates an error message. I was surprised by that; I tried to write a
closure in Rust as a nested function, and there's an specific error message
for that.

~~~
eridius
From the classic computer science point of view, you are correct in saying
that a lambda that does not capture in variables from its enclosing scope is
not a closure. But I think that's a meaningless distinction here that would
only serve to be confusing. Rust uses the terminology "closure" to refer to
this pipe syntax, regardless of whether it captures variables, and that's
fine. It's less confusing for people who aren't coming from a computer science
background, and it's not really even strictly speaking wrong. A closure is a
function coupled with an environment that allows it to capture values from its
scope. A closure that captures no variables can still have an environment, the
environment just happens to be null.

~~~
blaenk
I think it would be useful if the distinction did exist in Rust, so that for
example, "closures that have an empty environment" were indeed referred to as
lambdas, and lambdas had the guarantee of being Sync, Send, Copy, Clone, etc.,
since they're more or less just like regular `fn` items as far as I know. As
it is, a closure that captures nothing doesn't satisfy those bounds AFAIK, so
their use is more restrictive than it needs to be. Instead, you're forced to
write an actual `fn` definition, depriving you of the practicality and
conciseness of closure syntax.

~~~
dbaupp
A closure satisfies Send and Sync when it can, automatically. (I.e. with or
without captures.) Satisfying Clone when the contents are Clone would be
valuable for all closures, whether or not they capture anything.

The most valuable special case IMO for captureless closure would be allowing
them to coerce to (extern) fn types, useful for writing e.g. C callbacks
directly inline.

~~~
blaenk
Yeah, I forgot about that last point, which was the original reason I got this
idea.

