I don't agree. A lexical closure is exactly what it is. The main
distinguishing feature of C++ is that the free variables do not
automatically close over the entire lexical environment: they must be
specified in the capture list (which can of course be made to close
over the entire environment with '=').
Closures work by copying the captured variables, because they outlast
the lifetime of the surrounding environment (and which is why
overriding this by capturing free variables by reference in C++ is so
dangerous). What is meant by "copy" depends on the language.
Javascript for example copies simple numbers by value, and arrays,
objects and functions by reference (strings are immutable so there is
no difference), and most garbage collected languages do something
similar.
> [snip]
> In short, experience of other languages with mutable state and
> function values will not help much in understanding the C++ code in
> the question.
The important issue for a learner to understand is how free variables
in lambdas capture their lexical environment.
After that, the differences in behavior when copying the lambda (and how
often do you do that?) stem only from whether the lambda object, and
any free variables, are copied by reference or by value; this
difference being prompted in part by C++'s lifetime rules for automatic
objects. Copy by reference of lambda function objects can trivially
be implemented in C++ in the OP's code by changing 'auto bar = foo;' to
'auto& bar = foo;', which would then print "1 2 3".
The reverse (copying functions by value) in javascript would require
cloning the function object and all its captured variables. Java (as
opposed to javascript) and python do not permit mutation of free
variables at all. But all these different languages work, with C++, by
lexical closure by free variables.