I'm attempting to create a list of lists to imitate the functionality of a 2D array in Dart, and I was having trouble for a while figuring out how to make it work.
I originally used List.forEach
in order to create the lists and fill them, but after each loop, it's as if I never created the lists. Here's what that code looked like:
currentMap = new List<List<int>>(height);
currentMap.forEach((e) {
e = new List<int>(width);
e.forEach((f) {
f = 1;
});
});
Printing currentMap
resulted in a list of null
. Here's what I have now:
currentMap = new List<List<int>>(height);
for(int i = 0; i < height; i++) {
currentMap[i] = new List<int>(width);
for(int j = 0; j < width; j++) {
currentMap[i][j] = 1;
}
}
This works exactly as I expected it to.
I understand that this is probably a very basic issue, and I am assuming that forEach
does not allow you to modify the element, but I wanted some confirmation on that, and the Dart API docs do not specify except with the phrase "apples the function f to each element..." which may just not be clear to me.
Also, I am aware of things like the List.filled()
constructor -- this is just how I am starting to build towards other functionality.
EDIT: Okay, I think I understand now. Arguments are "pass-by-sharing" which means that a copy of a reference to the object is made. This means that you can modify a member of a mutable object that is pointed to by the argument (as follows):
void function(MyObject o) {
o.x = 5;
}
but trying to change what o
points to will not change the argument after exiting the function, such as this:
void function(MyObject o) {
MyObject p = new MyObject();
o = p;
}
Note that foreach does not modify the internal array pointer, which is used by functions such as current() and key(). It is possible to customize object iteration. In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.
The forEach method of an array does not modify the array, it just iterates over it. When you change the argument in the callback function, that doesn't affect the array either. Also, forEach doesn't do anything with the return values from the callback.
The for-each loop below cannot change the values in the array because only the loop variable value will change.
forEach() does not mutate the array on which it is called.
Dart does not have variable references, all elements are passed as a reference to an object, not to a variable. (In other words, Dart is purely "call-by-sharing" like both Java and JavaScript).
That means that the e
parameter to the forEach
callback is just a normal local variable, and assigning to it has no effect outside the callback. The same goes for iterators: they return the value in the iterable, but it has no reference back to the iterable after that.
The double loop is what you want when you do "read-modify-write". You read a value from the list, modify it and store it back into the list using the list's index-set operator.
I know you know about List.filled
, but just for other readers, I'll give the one-liner to create the two-dimensional array initialized to 1
values:
currentMap = new List.generate(height, (_) => new List.filled(width, 1));
This is because e
is only a reference to the List
in currentMap
not to a currentMap
item.
You update a copy of the reference to a List
, but this reference has no connection to currentMap
.
After the loop, e
just gets garbage collected.
This is because of how an Enumerator works and I believe because the Enumerator is immutable You can't modify the collection items when it's being processed in a foreach... removing members and such.
See also:
http://msdn.microsoft.com/en-us/library/ttw7t8t6.aspx
What is the best way to modify a list in a 'foreach' loop?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With