ActionScript Haxe Evaluate a referenced variable inside a loop in a closure - actionscript

I've been programming some stuff in ActionScript (Haxe) and arrived this very specific problem.
Here's the code (pseudo :S):
var func:Array = new Array(256);
(A) var i:Int = 0;
for(;i<256;i++) { // OR // for(i in 0...256) {
func[i] = function() { trace(i); }
}
func[0]();
func[127]();
func[256]();
The above code outputs (a):
256
256
256
I want that to be (b):
0
127
256
That doesn't happen, because ActionScript/Haxe is assigning the reference of i to the function, and since i equals 256 at the end of the loop where the functions get evaluated, that's why I get (a).
Does anyone know of a way to avoid that and get the expected results at (b) ?
Thanks to all of you guys and your responses.
I think I've found the answer. If you remove the line marked with (A) it works, if you leave it it doesn't. I'm pretty sure you could all figure out why that happens. Thanks again!

it's not neccessary to use callback, this should work as expected (haxe creates a local var in each loop):
var func = [];
for(i in 0...256)
func[i] = function() trace(i);
func[0]();
func[127]();

The one you show is the expected/desired behavior. To retain the value of "i" you must use "callback":
/* not pseudo code ;) */
var func = [];
for(i in 0...256)
func[i] = callback(function(v) trace(v), i);
func[0]();
func[127]();
func[256]();

Related

Can someone explain to me how this code works? Closure in Dart

I can't understand how the closure works in Dart. Why does BMW stay? This explanation causes my neurons to overheat. A lexical closure is a functional object that has access to variables from its lexical domain. Even if it is used outside of its original scope.
`void main() {
var car = makeCar('BMW');
print(makeCar);
print(car);
print(makeCar('Tesla'));
print(car('Audi'));
print(car('Nissan'));
print(car('Toyota'));
}
String Function(String) makeCar(String make) {
var ingane = '4.4';
return (model) => '$model,$ingane,$make';
}`
Console
Closure 'makeCar'
Closure 'makeCar_closure'
Closure 'makeCar_closure'
Audi,4.4,BMW
Nissan,4.4,BMW
Toyota,4.4,BMW
Calling car('Audi') is equal to calling (makeCar('BMW'))('Audi');
A lexical closure is a functional object that has access to variables from its lexical domain. Even if it is used outside of its original scope.
in simple english:
String make will stay valid as long as the returned function is not out of scope because the returned function has reference to String make.
In essence, you "inject" information needed for the newly created function. Your car knows that make is "BMW"
I think I figured it out. Here is an example where I left comments. Maybe it will help someone.
void main() {
var pr = funkOut(10); // assign a reference to an object instance
// of the Function class to the pr variable. pr is a closure because
// it is assigned a reference to an instance that contains a lexical
// environment (int a) and an anonymous function from this environment.
// 10 transfer to a
print(pr(5)); // 5 transfer to b //15
print(pr(10)); // 10 transfer to b //20
pr = funkOut(20);// 20 transfer to a
print(pr(5)); // 5 transfer to b //25
print(pr); // Closure: (int) => int
}
Function funkOut(int a) {
return (int b) => a + b;
}

Loop over a function and store as list

I have the following function that clicks a checkbox with splash:
local get_dimensions = splash:jsfunc([[
function () {
for i=1, 5 do
var rect = document.querySelector(string.format('checkbox[number="%d"]'), i)
.getClientRects()[0];
return {[rect.left]: rect.top};
end
}
]])
However, I cannot store a list from the loop into a single variable like rect, so how do I store a list into a variable, and when I return it, it should return a list of values?
Something similar to python, ie.:
def stuff():
rect = []
for i in range(5):
rect.append([...])
return rect
Let's take at your code.
You call splash:jsfunc. This function converts JavaScript into a Lua callable. It takes a single argument. A string that defines a JavaScript function.
yourString = [[
function () {
for i=1, 5 do
var rect = document.querySelector(string.format('checkbox[number="%d"]'), i).getClientRects()[0];
return {[rect.left]: rect.top};
end
}
]]
This looks like some weird mix of Lua and JavaScript.
This is how a JavaScript for loop looks like
for (let i = 0; i < 10; i++) {
// some code
}
This is how a Lua numeric for loop looks like:
Also what's the point of using return in a loop without any condition? This will be executed after the first cycle with i = 1. That's probably not what you want.
So fix the loop so it is JavaScript. Create a Object or Array and return that after the loop is complete.

How to mute jslint error on do{}while(false)

In this simple code:
do {
console.log('o');
} while (false);
jslint produces a warning on the last line saying Unexpected 'false'
I understand why, but I still want to mute it because in these cases that's how I want to have the control flow.
Let's look at what jslint expects in the while statement. From the source:
labeled_stmt('while', function () {
one_space();
var paren = next_token;
funct.loopage += 1;
advance('(');
step_in('control');
no_space();
edge();
this.arity = 'statement';
this.first = expected_relation(expression(0));
if (this.first.id !== 'true') {
expected_condition(this.first, 'unexpected_a');
}
no_space();
step_out(')', paren);
one_space();
this.block = block('while');
if (this.block.disrupt) {
prev_token.warn('strange_loop');
}
funct.loopage -= 1;
return this;
});
It mostly reads like English. 'while', one space, (, no space, expected expression, no space, ).
So let's look at what an expression(0) is. You can read through the source if you're really interested, but to be honest I can't really wrap my head around it either. Sorry. https://github.com/douglascrockford/JSLint/blob/master/jslint.js
As far as I can tell, though, expression(0) traverses the tree of operators and operands, and looks for values with a Right Binding Power greater than 0? And false has a binding power of 0? But variables and comparisons are okay here. I have no clue how that even works. Ask Crockford.
As for shutting up jslint, here is my suggestion:
/*jslint devel: true, continue: true */
var i = 0;
var forever = false;
do {
i = i + 1;
if (i < 5) {
continue;
}
console.log('o');
} while (forever);

Function with multiple names

In JavaScript you can do this to assign a function to multiple references:
z = function(){
console.log(1)
}
x = y = z
Now when we call x or y, 1 gets printed to the console.
Is this possible in dart?
Yes, just like in JavaScript, functions are first class citizens and can be assigned to variables.
Also see this somewhat older, but still relevant video Functions are Fun, Pt2.
As Example from the video:
loudPrint(String msg) {
print(msg.toUpperCase());
}
var loudify = loudPrint;
loudify('Dart is fun');
// DART IS FUN

How do you make foreach use non-reference types for delegates?

Example code that produces the problem:
import std.stdio, core.thread;
void main() {
ThreadGroup tg = new ThreadGroup();
foreach (int i; 1 .. 5)
tg.create( () => writeln(i) );
tg.joinAll();
}
Sample output:
3
5
5
5
5
(The expected output was the integers 1 through 5.)
I don't get why this is happening -- i is not a reference type, nor is there a reference to it being used in the delegate, so why does each thread use the value of i as whatever value it happens to have when the thread is scheduled, instead of the presumably pass-by-value value it's given?
I've made a handful of lame attempts like this, but nothing's been successful:
foreach (int i; 1 .. 5) {
scope j = i;
tg.create( () => writeln(j) );
}
I'm curious as to why this doesn't work, either. Is it not declaring a fresh j each time? Why does each thread refer to the same j (whose value is usually 5 by the time the threads get scheduled)?
so why does each thread use the value of i as whatever value it happens to have when the thread is scheduled, instead of the presumably pass-by-value value it's given?
It's pass-by-value as far as the loop body goes, however that does not apply to the threads created in it. The threads will still refer to i by its address.
To fix this problem, you need to create a closure inside the loop:
import std.stdio, core.thread;
void main() {
ThreadGroup tg = new ThreadGroup();
foreach (int i; 1 .. 5)
(i =>
tg.create( () => writeln(i) )
)(i);
tg.joinAll();
}
The lambda parameter will be stored in the closure, giving each thread its own copy.

Resources