Comments (4)
@magopian I didn't read the above comment (tl;dr) but just wanted to point out that your example of a closure returning a pure function wasn't correct.
Your example:
function (x) {
return function (y) {
return function (z) {
return z
}
}
}
According to @raganwald the definition of a closure is "a function containing one or more free variables". Since none of the functions above contain any free variables, they are all in fact pure functions, despite being nested.
That said, I think you're right that "contain" should be "return" in the context of the original challenge. A closure can contain a pure function pretty simply.
Consider this closure:
(x) => {
let foo = (a) => a
return foo(y * x)
}
I realize this is banal, but the closure above does "contain" the pure function foo
.
I can also think of a somewhat contrived example of a closure returning a pure function:
(x) =>
(y) => {
return z ? (a) => a : (a) => y * a
}
}
In this case, the first function (x) => ...
is pure but the second (y, z) => ...
is a closure which depends on the free variable z
and may return the pure function (a) => a
if z
is truthy but will otherwise return the closure (a) => y * a
if z
is falsy.
from javascript-allonge.
So, the conclusion is that it is possible that a closure both contains and returns a pure function?
from javascript-allonge.
👍
from javascript-allonge.
@magopian When you say:
even though it's pure, still is in a closure, and still needs its
parent's environment (so, its closure).
you are making assumptions, based on what you think is a necessary part of these closure statements, a return
statement which RETURNS
a function. Whereas there is no need to return
any of those function
s, although it makes more sense in the real world and also in the world of functional programming, but in the world of theoretical JavaScript concepts, you don't need to return the function
to have a closure
.
To Make it more clear I thought why not make an actual working example, which does the exact same thing without using the return
statement.
Before getting into the main part of my example let's say we have a storage
to store our functions, say for the sake of creating less pointers to them, although this pattern could have a lot of implications but here we just need it just to help us not create inline variables for our functions:
var FN = (function () {
var storage = [];
FN.has = function (id) {
return (typeof id === 'number' && id > -1 && id < storage.length);
};
function FN(fn) {
if (typeof fn === 'number') {
return storage[fn];
} else if (typeof fn === 'function') {
return (fn.__storeId__ = storage.push(fn) - 1);
} else {
console.warn('Invalid input parameter!');
}
}
FN.call = function (id) {
var fn = storage[id],
args;
if (typeof fn === 'function') {
args = Array.isArray(arguments[1]) ?
arguments[1] :
Array.prototype.slice.call(arguments, 1);
result = fn.apply(undefined, args);
return {
result: result,
call: function () {
if (typeof result === 'number' && FN.has(result)) {
return FN.call(result, Array.prototype.slice.call(arguments));
}
return null;
},
valueOf: function () {
return result;
}
};
} else {
console.warn('Invalid input parameter!');
}
};
return FN;
}());
I know the code block above may sound complicated, but let's use it as a black box and assume this allows us just to use closures without returning functions. the first code block I want to mention here is the code example in the book:
var fn = function (x) {
return function (y) {
return function (z) {
return x + y + z;
}
}
};
console.log(fn(10)(11)(6) == 27);
As we all know none of these functions is pure except for fn
itself.
Using FN
api we can transform it to:
var fn = function A(x) {
var fny,
fnyId;
fny = function (y) {
var fnz = function (z) {
function () {
}
return x + y + z
};
//here we store the 'fnz' function in storage
var fnzId = FN(fnz);
//here we only return a number not a function
return fnzId;
};
//here we store the 'fny' function in storage
fnyId = FN(fny);
//here we only return a number not a function
return fnyId;
};
//here 'fnId' is only a number not a function
var fnId = FN(fn);
This may seem much more code but I transformed it like this just to put comments, but the better syntax transformation could be:
var fnId = FN(function A(x) {
return FN(function (y) {
return FN(function (z) {
return x + y + z
});
});
});
Which is more like the first closure code block we have mentioned above, but with a big difference:
None of these function RETURNS functions.
and the way we could have this nested function call:
console.log(fn(10)(11)(6) == 27);
is like:
console.log(FN.call(fnId, 10).call(11).call(6) == 27);
As you see we get almost the same result using only numbers, without passing functions around.
the idea here is now if you do:
var fnId = FN(function (x) {
return FN(function (y) {
return FN(function (z) {
return z;
});
});
});
console.log(FN.call(fnId, 10).call(11).call(6) == 6);
the most inner function which as it is mentioned on the book is:
the I Combinator or Identity Function
is a pure function and if you save its storeId
somewhere like:
var mostInnerfnId;
var fnId = FN(function (x) {
return FN(function (y) {
return (mostInnerfnId = FN(function (z) {
return z;
}));
});
});
And then if you call right to its upper function:
FN.call(fnId, 10).call(11);
Now you can have access to this function like:
var fn = FN(mostInnerfnId);
which can be called as a pure standalone function:
fn(26);//output: 26
All the code above here is just to clarify one single point. The way closure environment
object gets managed doesn't have anything to do with returning functions, it is all about containing or having nested function definitions and pure functions are always pure no matter if you return them or not. Basically when you say:
In this case, the function (z) { return z }, even though it's pure,
still is in a closure, and still needs its parent's environment (so,
its closure).
as it is called in my last code block, it doesn't need its parent's environment object. It only needs to get defined, then you could call it anywhere.
Hope this could be helpful.
from javascript-allonge.
Related Issues (20)
- Incorrect syntax in `get` method of `ModelMaker` function
- Queue implementation memory leak?
- Broken internal links
- do while example issue HOT 1
- Imtiyaz40
- Fix minor type in closures.md
- Chapter 1, Closures and Scope, grandparents example
- Chapter 1, Closures and Scope, inserting empty environment
- Chapter 4 - Modules : example returns uninitialized variables
- Copying text from PDF no longer works on OS X
- typo in fluent.md
- i don't understand a sentence HOT 3
- Please explain YouAreDaChef reference (and vilification) HOT 1
- Native Array Map function (Question)
- Chapter 1, Summary / Is correction needed?
- Unexpected result when using function maybe together with mapWith.
- A better "extend" function. Any comments ?
- Use {:lang="js"} everywhere for consistency
- Not all code blocks are annotated with {:lang="js"} HOT 1
- Parentheses in Decorators
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from javascript-allonge.