A list of Dart StringBuffers seem to interfere with each other - dart

I'm doing a nested iteration over two lists, in which I am populating some StringBuffers, like this:
var int_list = [1, 2, 3];
var letters_list = ['a', 'b', 'c'];
var row_strings = List.filled(3, StringBuffer());
var single_buffer = StringBuffer();
int_list.asMap().forEach((int_index, column) {
letters_list.asMap().forEach((letter_index, letter) {
// debug the writing operation
print('writing $letter_index - $letter');
row_strings[letter_index].write(letter);
// try a buffer not in a list as a test
if (letter_index == 0) {
single_buffer.write(letter);
}
});
});
print(single_buffer);
print(row_strings);
What I expect to happen is that in the list of StringBuffers, buffer 0 gets all the 'a's, buffer 1 gets all the 'b's, and buffer 3 the 'c'.
The debug output confirms that the writing operation is doing the right thing:
writing 0 - a
writing 1 - b
writing 2 - c
writing 0 - a
writing 1 - b
writing 2 - c
writing 0 - a
writing 1 - b
writing 2 - c
and the single string buffer gets the right output:
aaa
But the output of the list is this:
[abcabcabc, abcabcabc, abcabcabc]
What is going on here? There seems to be some strange behaviour when the StringBuffers are in a list.

Your problem is this line:
var row_strings = List.filled(3, StringBuffer());
This constructor is documented as:
List.filled(int length, E fill, {bool growable: false})
Creates a list of the given length with fill at each position.
https://api.dart.dev/stable/2.10.5/dart-core/List/List.filled.html
So what you are doing is creating a single StringBuffer instance and uses that on every position in your row_strings list.
What you properly want, is to create a new StringBuffer for each position in the list. You need to use List.generate for that:
List.generate(int length,E generator(int index), {bool growable: true})
Generates a list of values.
Creates a list with length positions and fills it with values created by calling generator for each index in the range 0 .. length - 1 in increasing order.
https://api.dart.dev/stable/2.10.5/dart-core/List/List.generate.html
Using that, we end up with:
final row_strings = List.generate(3, (_) => StringBuffer());
We don't need the index argument in our generator so I have just called it _. The function (_) => StringBuffer() will be executed for each position in the list and saved. Since out function returns a new instance of StringBuffer each time it is executed, we will end up with a list of 3 separate StringBuffer instances.

Related

How to iterate over a compile-time seq in a manner that unrolls the loop?

I have a sequence of values that I know at compile-time, for example: const x: seq[string] = #["s1", "s2", "s3"]
I want to loop over that seq in a manner that keeps the variable a static string instead of a string as I intend to use these strings with macros later.
I can iterate on objects in such a manner using the fieldPairs iterator, but how can I do the same with just a seq?
A normal loop such as
for s in x:
echo s is static string
does not work, as s will be a string, which is not what I need.
The folks over at the nim forum were very helpful (here the thread).
The solution appears to be writing your own macro to do this. 2 solutions I managed to make work for me were from the users mratsim and a specialized version from hlaaftana
Hlaaftana's version:
This one unrolls the loop over the various values in the sequence. By that I mean, that the "iterating variable s" changes its value and is always the value of one of the entries of that compile-time seq x (or in this example a). In that way it functions basically like a normal for-in loop.
import macros
macro unrollSeq(x: static seq[string], name, body: untyped) =
result = newStmtList()
for a in x:
result.add(newBlockStmt(newStmtList(
newConstStmt(name, newLit(a)),
copy body
)))
const a = #["la", "le", "li", "lo", "lu"]
unrollSeq(a, s):
echo s is static
echo s
mratsim's version:
This one doesn't unroll a loop over the values, but over a range of indices.
You basically tell the staticFor macro over what range of values you want an unrolled for loop and it generates that for you. You can access the individual entries in the seq then with that index.
import std/macros
proc replaceNodes(ast: NimNode, what: NimNode, by: NimNode): NimNode =
# Replace "what" ident node by "by"
proc inspect(node: NimNode): NimNode =
case node.kind:
of {nnkIdent, nnkSym}:
if node.eqIdent(what):
return by
return node
of nnkEmpty:
return node
of nnkLiterals:
return node
else:
var rTree = node.kind.newTree()
for child in node:
rTree.add inspect(child)
return rTree
result = inspect(ast)
macro staticFor*(idx: untyped{nkIdent}, start, stopEx: static int, body: untyped): untyped =
result = newStmtList()
for i in start .. stopEx: # Slight modification here to make indexing behave more in line with the rest of nim-lang
result.add nnkBlockStmt.newTree(
ident("unrolledIter_" & $idx & $i),
body.replaceNodes(idx, newLit i)
)
staticFor(index, x.low, x.high):
echo index
echo x[index] is static string
Elegantbeefs version
Similar to Hlaaftana's version this unrolls the loop itself and provides you a value, not an index.
import std/[macros, typetraits]
proc replaceAll(body, name, wth: NimNode) =
for i, x in body:
if x.kind == nnkIdent and name.eqIdent x:
body[i] = wth
else:
x.replaceAll(name, wth)
template unrolledFor*(nameP, toUnroll, bodyP: untyped): untyped =
mixin
getType,
newTree,
NimNodeKind,
`[]`,
add,
newIdentDefs,
newEmptyNode,
newStmtList,
newLit,
replaceAll,
copyNimTree
macro myInnerMacro(name, body: untyped) {.gensym.} =
let typ = getType(typeof(toUnroll))
result = nnkBlockStmt.newTree(newEmptyNode(), newStmtList())
result[^1].add nnkVarSection.newTree(newIdentDefs(name, typ[^1]))
for x in toUnroll:
let myBody = body.copyNimTree()
myBody.replaceAll(name, newLit(x))
result[^1].add myBody
myInnerMacro(nameP, bodyP)
const x = #["la", "le", "Li"]
unrolledFor(value, x):
echo value is static
echo value
All of them are valid approaches.

Problem of understading the programing syntax of DART recursion [duplicate]

I have trouble understanding the code of this recursive function. I am new to DART programming. I understand what a recursive function accomplishes, but I have a problem understanding the programming syntax.
int sum(List<int> numberList, int index) {
if (index < 0) {
return 0;
} else {
return numberList[index] + sum(numberList, index - 1);
}
}
main() {
// Driver Code
var result = sum([1, 2, 3, 4, 5], 4);
print(result);
}
Question: where is the value for each step stored- Does the result for the first pass at line 5 equals 9 taken the inputs from line 11. Where is the value of result 9 stored? How does the function know to add 9 + 3 in the second pass?
Does the recursive function have "internal memory" of the values generated by each pass?
My understanding of the programing language would be that var result passes the arguments to the sum function.
The sum function executes the if-else command until the index value is 0, which means it executes 4 times. With the first pass the return command creates a value of 9 (5 + 4 since value of index is 5 and value of index-1 is 4).
Here begins my confusion. The sum function would now do a second if-else pass and execute the return command again.
Now the initial value of numberList[index] would need to be 9 and the value of sum(numberList, index - 1); would need to be 3, to get 9 + 3 = 12. Additional 2 passes gets 12 + 2 = 14 and 14 + 1 = 15 the expected result.
My question here is how does (if it does) the index value in the "numberList[index]" changes. The index value is defined as 4. Is this an internal logic of the recursive function or am I completely misinterpreting the programming syntax? I would expect that we have a "temporary" variable for the result which increases with each pass.

box callback functions returning the same string in Rascal

I'm trying to draw some boxes in Rascal and trying to give each box its own callback function. On entering the box with the mouse the corresponding string should get displayed in the text element (so hovering box1 should display box1 etc.).
However, at the moment the text does pop up but just displays "box3" for each of the 3 boxes.
Any ideas?
strings = ["box1", "box2", "box3"];
boxes = [ box(
size(100, 100),
onMouseEnter(void() {
output = s;
})
) | s <- strings];
render(hcat([
vcat(boxes),
text(str () {return output;})
]));
Good question, classical problem. The essence of the problem is that Rascal uses "non-capturing closures": this means that functions that are returned from another function share the same context. In your case this is the variable s introduced by s <- strings. This nearly always happens when you create function values in a loop (as you do here). The solution is to wrap another function layer around the returned function.
Here is a simple example:
list[int()] makeClosures()
= [ int() {return i;} | i <- [0,1,2]];
void wrong(){
lst = makeClosures();
println(lst[0]());
println(lst[1]());
println(lst[2]());
}
which will print surprisingly the values 2,2and2`. The solution is, as said, to introduce another function level:
int() makeClosure(int i)
= int() { return i;};
list[int()] makeClosuresOK()
= [ makeClosure(i) | i <- [0,1,2]];
void right(){
lst = makeClosuresOK();
println(lst[0]());
println(lst[1]());
println(lst[2]());
}
now calling right() will print 1, 2, and 3 as expected.
I leave it as an exercise how this is done in your example, but I am prepared to give a solution when you ask for it. Good luck!

List use of double dot (.) in dart?

Sometimes I see this
List list = [];
Then list..add(color)
What's the difference between using 1 dot(.) and 2 dot(..)?
.. is known as cascade notation. It allows you to not repeat the same target if you want to call several methods on the same object.
List list = [];
list.add(color1);
list.add(color2);
list.add(color3);
list.add(color4);
// with cascade
List list = [];
list
..add(color1)
..add(color2)
..add(color3)
..add(color4);
It's the cascade operator of Dart
var l1 = new List<int>()..add(0)..addAll([1, 2, 3]);
results in l1 being a list [0, 1, 2, 3]
var l1 = new List<int>().add(0).addAll([1, 2, 3]);
results in an error, because .add(0) returns void
.. (in the former example) refers to new List(),
while . (in the later) refers to the return value of the previous part of the expression.
.. was introduced to avoid the need to return this in all kinds of methods like add() to be able to use an API in a fluent way.
.. provides this out of the box for all classes.
Cascades (..) allow you to make a sequence of operations on the same object. read doc for details
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
The previous example is equivalent to:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
Double dots(..) also know as cascade operator
It allows you to not repeat the same target if you want to call several methods on the same object.
e.g without double dots
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
But after using “..”, the above code will be written like this:
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
Triple dots(…) i.e. Spread Operator
“… ”also known as spread operator which provide a concise way to insert multiple values into a collection.
You can use this to insert all the elements of a list into another list:
Normally we use .add() or .addAll() to add data to the list like:
var list = [1, 2, 3];
var list2=[];
list2.addAll(list);
After using “…” we will write code like this:
var list = [1, 2, 3];
var list2 = [0, ...list];
.. Is known as the cascading operator in dart.
It allows you to use more than one subsequence operation:
Examples:
banerad..load()..show().
List coursename;
coursename..add("java")..add("flutter" )..add("dart");
Here is another example

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