I started learning about functional programming and I'm a bit confusing about it.
My question is: is Java lambdas equivalent to JavaScript closures? If not, what is the difference between them?
They are "slightly different" and also "roughly equivalent".
tldr; a Java lambda that access an outer-scoped variable1 is also a closure; and a JavaScript "closure" that does not access an outer-scope variable is not strictly a closure (and can be more precisely called an anonymous function2).
In JavaScript, a closure generally implies "being able to re-assign variables in the outer scope" - however, having access to or "closing over / binding" a variable is sufficient for an anonymous function to be a closure3.
Java lambda's requires that all variables from the outer scope accessed in a lambda are effectively final which means they cannot be re-assigned.
1The rule is that a [Java] lambda expression can only access local variables from an enclosing scope that are effectively final. An effectively final variable is never modified—it either is or could be declared as final - http://www.informit.com/articles/article.aspx?p=2303960
However, since a Java lambda can capture a read-only variable binding to mutable objects, it is possible for a Java lambda to indirectly modify state in the outer context and can thus emulate the ability to "re-assign" values.
2In computer science, a closure is a function that has an environment of its own. Inside this environment, there is at least one bound variable [and] anonymous functions are sometimes wrongly called closures. This is probably because most languages [eg. JavaScript] that have anonymous functions also have closures and it's common for programmers to learn about both at the same time. - https://simple.wikipedia.org/wiki/Closure_(computer_science)
Java also has different semantics on this inside a lambda vs a JS anon-function / closure; also see JavaScript "arrow functions" which have different rules than traditional anonymous functions on how this behaves.
3 Trivial argument:
Haskell has closures.
Haskell does not allow variables to be re-assigned.
Therefore, re-assignment (or mutability) is not a requirement of closures.
No, they are not equivalent. One has to do with syntax and the other with memory.
Lambdas are a short-hand syntax for declaring anonymous code structures.
Closures are when a nested function (named or not) holds a reference to a variable from a function in an outer scope. That, in and of itself isn't really an issue. But, when the nested function persists longer than the outer scoped variable, the variable won't be garbage collected when the outer scope terminates. That's when closures become either very powerful or very annoying. It all depends on if you are intentionally using them or not. Closures can allow for shared access to private data.
Related
In his (great) series of books “You don't know JS", Kyle Simpson states that dynamic scope and this mecanism are "near cousin", he also says that :
"the this mechanism is kind of like dynamic scope."
(YDKJS, Scope and Closure, Appendix A)
What is preventing him from saying that this is plain and simple dynamic scoping ?
Also, in the book "this & Object Prototypes", also part of the series YDKJS, as far as I can say, Kyle is not mentioning once dynamic scope while discussing how thisis working, so I am a bit surprised why he decided to not go further in the analogy... Does anyone have an idea why ?
Thanks
The reason I claim this is just "kind of like" a dynamic scope and not actually a dynamic scope is based on these two observations:
The aesthetic of accessing the "scope context" explicitly with an object reference (this.foo = 1) is distinct from implicitly accessing it via lexical variable reference (foo = 1). At best, this makes the two systems of "scope" parallel, not the same. But there's more different than what it seems on the surface!
But more importantly, dynamic scopes are traditionally defined as scope chains that are based on the call-stack. That is, a dynamic scope is one where the decision of what "scope contexts" to consult, in order, is exactly the current stack of function calls. But this isn't based on the call-stack, per se, but rather just the manner in which the most recent call in the stack was made, only.
Consider this scenario: foo() calls bar(), bar() calls baz(), and in baz() a reference is made to an x variable that is not defined in baz().
In lexical scope, the lookup would be baz(), then whatever the outer scope of baz() is, and so on. bar() and foo() wouldn't be consulted at all, unless they happened to be the lexically surrounding scopes of baz().
In dynamic scope, the call stack foo() -> bar() -> baz() is the scope chain, so baz() is consulted, then bar(), then foo(), regardless of where those 3 functions exist lexically in the code base.
Now, consider the same scenario, but this.x is the reference made inside baz(). The call stack foo() -> bar() -> baz() is not particularly relevant in resolving this.x. Rather, the only thing that matters is how baz() was invoked. If the call site is baz(), the "default binding" rule applies. If it's this.baz(), the "implicit binding" rule applies. If it's baz.call(..), the "explicit binding" rule applies. And if it's new baz(), the "new binding" rule applies. That's it.
Actually, it's not the only thing, it's just the first decision that's made. Once it's determined what object (aka scope context object) this points to, now the only thing that matters is the prototype chain of that object, as that's the "scopes" that will be consulted, in order of the prototype chain linkage.
Summary:
In lexical scope, where a function is defined is the only thing that determines what contexts are used, and in what order, to resolve a variable reference.
in dynamic scope, where a function is called from is the only thing that determines what contexts are used, and in what order, to resolve a variable reference.
in this-based context, neither where a function is defined nor where it's called from are relevant. Therefore, this is neither lexical scoping nor dynamic scoping.
The only thing that matters here is how the current function in the call stack (top of the stack) was called. Well, that's the only thing that matters to determine which scope chain to start the lookup on. But once that object is decided, it's now that object's prototype chain that entirely defines the scope resolution.
Because the this "variable" is the only variable that has dynamic scope, all other ("real") variables have lexical scope in JavaScript. In contrast, in "plain and simple dynamic scoping", all variables have dynamic scope and you can't get away from it (which is really ugly). So when we want to have multiple values in our dynamic scope, we store them in an object, and access them as properties of the this object, which is quite different from dynamic scope and also involves object inheritance.
The ES6 standard comes up with Temporal Dead Zones, making a variable reference not possible in any way until the lexical binding is evaluated. So what does variable creation at the time of lexical environment initialisation mean to
The programmer ?
The Compiler ?
The declaration of a variable using var declaration might mean something to the programmer previously, but now with TDZ in place does javascript start behaving like java for this purpose? Is there any reason other than the way javascript interpreter works that we have hoisting (as a result TDZ) in the first place?
What happens when a lexical binding is encountered later in the code due to order of execution even when the code appears before it lexically?
let abc = f();
let b;
f(){ return b;}
When does traditionally programming languages like java create variables? When the variable declaration is encountered? or when the lexical scope is initialised?
I have a feeling that the creation of TDZ had to do with it being a very menial step from var, whereas if they were to go with the seemingly more logical approach of not even having the identifier exist, the engine would have had to undergo even more intensive changes. As for the second part of your question in reference to when other languages "create" variables, there are many other important factors to consider that you seem to have left out, such as is the language interpreted vs compiled, as well as there are multiple different steps to "creating" a variable. It acts differently in many different cases, and there is no single answer. In fact, that is one of the big reasons why there are many different languages.
As for your coding question, it would depend on when you're calling your f function, since function declarations are hoisted in javascript. If you are calling it before b is declared, then you are in a TDZ and b cannot be referenced. It will behave very similarly as if you were simply putting the return b wherever this function is called.
Honestly, it seems as if there is some underlying misunderstanding of javascript, and computer languages in general. Javascript is not "behaving" more like java, in fact the new let keyword has very nuanced behavior, such as being able to be block scoped, compared to type/variable declarations in java. I would suggest not trying to think of the changes in ES6 in terms of other languages; javascript is not like a lot of other languages, it will be very difficult to understand the concepts and how you should be programming with javascript if you do.
EDIT:
As for why there is variable and function declaration hoisting, that is easily googlable.
So what does variable creation at the time of lexical environment
initialisation mean to the programmer?
Not much. A programmer only intends to use declared and initialised variables.
That the variable is available in the whole scope (from the beginning) only means that mistakes will be caught easier, as the usage of the variable prior to initialisation fails (with an exception) instead of silently being resolved to an outer-scope (global?) variable. It also means that the identifier, regardless where in the scope it is used, always refers to the local variable - which is just what we'd expect from a scope.
So what does variable creation at the time of lexical environment
initialisation mean to the Compiler?
That a lexical environment doesn't change its structure during execution. Static resolution of identifiers in a known scope makes compiling possible, and execution faster.
Just as a counterexample, consider this thing:
var x = "global";
var code = "var x = 'local';";
(function() {
"use sloppy";
function test() {
console.log(x); // what do you think does `x` refer to?
} // It's hard to understand as a developer,
// now imagine being a compiler that tries to optimise `test`.
test();
eval(code);
test();
}());
What happens when a lexical binding is encountered later in the code
due to order of execution even when the code appears before it lexically?
b is used by the call to f() before it's initialised. Accessing it throws a TDZ exception.
You can try it online.
I'm not too familiar with JavaScript's mechanics of scope resolution.
I was wondering, how expensive is it for JavaScript to access variables that are one or two scopes "upwards" in the scope chain?
Say I have a function named scope3 that is inside a function named scope2 which is inside a function named scope1.
If I try to access a variable defined in scope1 from scope3, does JavaScript have to load all variables in all three scopes in order to find it? If so, the expensiveness of such operation depends on how many variables are defined in each scope, correct?
The doubt arose because I have multiple functions that make use of the same elements or values. Values that require a function call to be calculated.
So, I was wondering if it is more efficient to retrieve the elements and re-calculate the values in each function, to avoid climbing the scope chain, or if it is best to wrap the functions inside an outer scope, retrieve the elements / calculate the values only once, and then simply access them from the inner functions.
This, of course, is a semplified example of my structure. In reality I have multiple scoping levels.
What is best-practice for cases like this?
Thank you.
I create a small jsperf test to have an idea.
v8 (chromium) is super fast when there is no closure, but a lot slower with closure. How 'far' it has to reach to get the variable is not relevant.
Spidermonkey (firefox) is slower (50% of chrome max speed) but the speed is consistent.
So as a first approximation, you can consider closures to be slower. The number of nesting level has no impact on speed though.
You could pass the variable as parameter (if possible in your code), it's not expensive and it's cleaner.
Is there any memory usage difference between anonymous functions and normal functions in Javascript ?
If so, how? Can you explain it?
If by "normal functions" you mean functions declared as function a(){ at the root level of your script, that is functions attached to the window object, yes there are differences :
functions attached to the window object aren't garbaged while anonymous functions can be garbaged as soon as you don't use them anymore.
they might slow the access to other variables of the window object (attaching the function at the root level is sometimes qualified of "cluttering global namespace" but the reason to avoid it is mainly to have a cleaner code and avoid name collisions).
anonymous functions are closures : they keep a pointer to their enclosing scope, which enables the use of the variables defined in this scope. A side effect is that this scope cannot be garbaged before the function so the function can be heavier than you think and than a "normal function" (you can add an empty scope to enclose the anonymous declaration and prevent this effect if you don't need the variables of the scope but as I don't know if javascript engines can yet optimize away part of the enclosing scope I suggest you don't do it if you don't detect circular references).
But those differences are usually minor, you normally don't have to pay attention to that. In most of your pages your anonymous functions wouldn't be garbaged anyway as you don't remove the event handler (the first root cause of anonymous functions usually).
Globally (premature optimization is the root etc.) I recommend you favor readability as long as you don't have garbaging problems. Javascript engines and their GC change a lot, so your efforts could be useless.
Google has an interesting notice about closure and memory.
What is the difference between a closure and an anonymous function in JavaScript
The closure mechanism applies to all JavaScript functions, whether anonymous or not.
I think confusion between the two concepts comes from use of the term "closure" where an author has said something like "the following code creates a closure" and then given an example that happens to use an anonymous function. In such instances typically the closure mechanism is what is important to make the particular piece of code work as intended, while use of an anonymous function rather than a named function just happens to be a convenient way to code it. People reading such examples and seeing "closure" for the first time then misinterpret the term and go on to use it incorrectly in their own Stack Overflow or blog posts and so the confusion spreads.
A closure is an expression relying on a namespace reference in which variables are resolved (a context). An anonymous function is one way to form a closure in Javascript - a named function is another.
There is some discussion about the ability to form closures with non-function blocks, but the current standards specify no such.
http://jibbering.com/faq/notes/closures/ is a pretty good description.
A closure is a function that has captured its environment (the variables that it has access to)
It can be created both from an anonymous and as from named function.
And an anonymous function differs from a named function mainly that it's declaration does not get hoisted to top of the scope.