473,406 Members | 2,710 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Lexical scope and looping

I would expect this code:

globalFnArray = [];
for (var i = 0; i < 5; i++) { globalFnArray.push (function () { alert
(i) }); }
for (var j = 0; j < 5; j++) { globalFnArray[j](); }

to alert 0, 1, 2, 3, and 4.

Instead, I get 5, 5, 5, 5, and 5 in Firefox, indicating that all of
the functions in globalFnArray are closing over the final value of i
(after the for loop's conditional (i < 5) has failed and the loop has
exited), rather than the value to which i was bound during the
iteration of the loop when the function was defined. This does not
seem consistent with lexical scope as I understand it. Is the for loop
a special case? I'd appreciate any suggestions as to what I'm missing.

Thanks,
--Eli

Apr 4 '07 #1
6 2008
<en*****@gmail.comwrote in message
news:11*********************@o5g2000hsb.googlegrou ps.com...
>I would expect this code:

globalFnArray = [];
for (var i = 0; i < 5; i++) { globalFnArray.push (function () { alert
(i) }); }
for (var j = 0; j < 5; j++) { globalFnArray[j](); }

to alert 0, 1, 2, 3, and 4.

Instead, I get 5, 5, 5, 5, and 5 in Firefox, indicating that all of
the functions in globalFnArray are closing over the final value of i
(after the for loop's conditional (i < 5) has failed and the loop has
exited), rather than the value to which i was bound during the
iteration of the loop when the function was defined. This does not
seem consistent with lexical scope as I understand it. Is the for loop
a special case? I'd appreciate any suggestions as to what I'm missing.
I am not entirely sure how this relates to scope.

The problem is that you are storing functions with a variable inside them. Let me just
illustrate. What is being stored in each call to push() is:

function () {
alert(i);
}

So, when you finally call the function, i has already reached 5, and of course stays
there.

So each call iteration through globalFnArray will result in alert('5'); The only way I
see of you achieving what you want is:

globalFnArray = [];
for (var i = 0; i < 5; i++)
{
globalFnArray.push(function()
{
alert(i);
});
}
for (var i = 0, j = 0; j < 5; i++, j++)
{
globalFnArray[j](i);
}

*OR* change just these lines:

globalFnArray.push(function() to globalFnArray.push(function(i)

Then you could globalFnArray[j](i) anywhere you wanted, as long as it is fed a variable of
i.

-Lost
Apr 4 '07 #2
"-Lost" <mi*********@comcast.netwrote in message
news:wK******************************@comcast.com. ..
<en*****@gmail.comwrote in message
news:11*********************@o5g2000hsb.googlegrou ps.com...
>>I would expect this code:

globalFnArray = [];
for (var i = 0; i < 5; i++) { globalFnArray.push (function () { alert
(i) }); }
for (var j = 0; j < 5; j++) { globalFnArray[j](); }

to alert 0, 1, 2, 3, and 4.

Instead, I get 5, 5, 5, 5, and 5 in Firefox, indicating that all of
the functions in globalFnArray are closing over the final value of i
(after the for loop's conditional (i < 5) has failed and the loop has
exited), rather than the value to which i was bound during the
iteration of the loop when the function was defined. This does not
seem consistent with lexical scope as I understand it. Is the for loop
a special case? I'd appreciate any suggestions as to what I'm missing.

I am not entirely sure how this relates to scope.

The problem is that you are storing functions with a variable inside them. Let me just
illustrate. What is being stored in each call to push() is:

function () {
alert(i);
}

So, when you finally call the function, i has already reached 5, and of course stays
there.

So each call iteration through globalFnArray will result in alert('5'); The only way I
see of you achieving what you want is:

globalFnArray = [];
for (var i = 0; i < 5; i++)
{
globalFnArray.push(function()
{
alert(i);
});
}
for (var i = 0, j = 0; j < 5; i++, j++)
{
globalFnArray[j](i);
Oops! Here I meant:

globalFnArray[j]();
}

*OR* change just these lines:

globalFnArray.push(function() to globalFnArray.push(function(i)

Then you could globalFnArray[j](i) anywhere you wanted, as long as it is fed a variable
of i.

Apr 4 '07 #3
The problem is that you are storing functions with a variable inside them.

Yes, I am trying to make a closure.

However, after further experimentation I've realized that I did
misunderstand lexical scope -- I thought that functions could close
over a variable value at the point in a lexical block (such as a
function definition) at which they were defined, but in fact they can
only close over the last value in that lexical block, irrespective of
where in the block the function is defined.

So I think the way to do what I was trying to do is:

globalFnArray = [];

for (var i = 0; i < 5; i++) {
globalFnArray.push (
function () {
var x = i;
return function () { alert (x) }
}()
);
}

for (var j = 0; j < 5; j++) { globalFnArray[j](); }

If there is a nicer way to do this which doesn't require using a
throwaway variable, I'd love to know.

Thanks,

--Eli

Apr 5 '07 #4
On Apr 4, 8:45 pm, enae...@gmail.com wrote:
If there is a nicer way to do this which doesn't require using a
throwaway variable, I'd love to know.
You could use a constructor to create the function type for what
you're trying to do:

globalFnArray = [];

function alertfunc(x) {
return function() { alert(x); };
}

for (var i = 0; i < 5; i++) {
globalFnArray.push ( new alertfunc(i) );
}

for (var j = 0; j < 5; j++) { globalFnArray[j](); }
Still not the prettiest thing, but maybe more like what you're looking
for?

- Kevin

Apr 6 '07 #5
On Apr 5, 10:45 am, enae...@gmail.com wrote:
The problem is that you are storing functions with a variable inside them.

Yes, I am trying to make a closure.
You did, but to a global variable (i). In this case, you can set i to
whatever value you want later, all the functions will show the same
value.
>
However, after further experimentation I've realized that I did
misunderstand lexical scope -- I thought that functions could close
over a variable value at the point in a lexical block (such as a
function definition) at which they were defined, but in fact they can
only close over the last value in that lexical block, irrespective of
where in the block the function is defined.
"close over"? All the function objects that you put in the array have
a reference back to the same i variable, which is global. Consider:

var gArray = [];

function foo(){

// This i is local to foo
for (var i=0; i<5; i++){

// Each fn has a closure back to foo's i
gArray.push( function(){alert(i);} );
}
}

foo();

// This i is global
for (var i=0, len=gArray.length; i<len; i++){
gArray[i]();
}

>
So I think the way to do what I was trying to do is:

globalFnArray = [];

for (var i = 0; i < 5; i++) {
globalFnArray.push (
function () {
var x = i;
return function () { alert (x) }
}()
);

}

for (var j = 0; j < 5; j++) { globalFnArray[j](); }

If there is a nicer way to do this which doesn't require using a
throwaway variable, I'd love to know.
You aren't throwing away the variable at all, you are putting it into
the new function object with the value of whatever i was when you
create the function.

Anyhow, you have to break the closure somehow. You can also use a new
Function, however I think the above way is better as its much more
efficient - new Function is similar to using eval. But for the
record:

for (var i=0; i<5; i++){
gArray.push( new Function('alert(' + i + ');') );
}
--
Rob

Apr 6 '07 #6
On Apr 4, 5:45 pm, enae...@gmail.com wrote:
The problem is that you are storing functions with a variable inside them.

Yes, I am trying to make a closure.

However, after further experimentation I've realized that I did
misunderstand lexical scope -- I thought that functions could close
over a variable value at the point in a lexical block (such as a
function definition) at which they were defined, but in fact they can
only close over the last value in that lexical block, irrespective of
where in the block the function is defined.

So I think the way to do what I was trying to do is:

globalFnArray = [];

for (var i = 0; i < 5; i++) {
globalFnArray.push (
function () {
var x = i;
return function () { alert (x) }
}()
);

}

for (var j = 0; j < 5; j++) { globalFnArray[j](); }

If there is a nicer way to do this which doesn't require using a
throwaway variable, I'd love to know.
for (var i = 0; i < 5; i++) {
globalFnArray.push (
function (myPosn) {
return function () { alert (myPosn); }
}(i)
);
}
--
../rh

Apr 6 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Matt Knepley | last post by:
I must be misunderstanding how Python 2.3 handles lexical scoping. Here is a sample piece of code: def run(): a = 1 def run2(b): print a run2(2) print a run()
0
by: Collin VanDyck | last post by:
Hello! I have set up a pluggable SAX transformation pipeline which is made up of individual nodes that transform the source XML, and for the most part it works well. Each node in the pipeline...
13
by: Lucas Zimmerman | last post by:
Is there any Lex code available that describes how to scan C programs? I'd like to read someting related to this. One of my doubs is how C deals with ambiguities, for example, `a = x/*p;' or `a =...
19
by: Dave | last post by:
I'm building a research application that needs to be a super speed demon. I decided that one way to do this is to use goto loops instead of while() loops when I need them. that way, instead of...
18
by: jslowery | last post by:
I am not completely knowledgable about the status of lexical scoping in Python, but it was my understanding that this was added in a long time ago around python2.1-python2.2 I am using python2.4...
2
by: Frank-René Schäfer | last post by:
penSource Project 'Quex': http://quex.sf.net Last weekend, the lexical analyser generator 'Quex' has been released on SourceForge. Quex provides advanced features for mode definitions and...
14
by: Khookie | last post by:
Woah... is it just me or do C programmers don't bother talking about how cool C can be (compared to Lisp, Haskell, etc.) - functionally speaking? // Lexical scoping - via nested functions...
3
by: globalrev | last post by:
i cant figure outif python has lexical or general scope. it seems functions have lexical scope but with some restrictions and some non-function scopes are dynamic?
9
by: mrstevegross | last post by:
I ran into a weird behavior with lexical scope in Python. I'm hoping someone on this forum can explain it to me. Here's the situation: I have an Outer class. In the Outer class, I define a...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.