Re: Deprecation: foreach: loop index implicitly converted from size_t to int

2024-05-11 Thread BoQsc via Digitalmars-d-learn
A horrible alternative would be to use `alias` on `size_t` to 
make up a new pseudo-type that is more aligned with the code 
logic.


```
alias integer = size_t;
import std.stdio : writefln;

void main() {
auto arr = [
[5, 15],  // 20
[2, 3, 2, 3], // 10
[3, 6, 2, 9], // 20
];

foreach (integer i, row; arr)
{
double total = 0.0;
foreach (e; row)
total += e;

auto avg = total / row.length;
writefln("AVG [row=%d]: %.2f", i, avg);
}
}
```


Re: Deprecation: foreach: loop index implicitly converted from size_t to int

2024-05-03 Thread BoQsc via Digitalmars-d-learn
Well all these proposals to `int` index like `size_t` and `const 
typeof(arr.length)` are cryptic and less readable and less 
straightforward in comparison to how it used to be. Feels like 
horrible decision if the language is suppose to be somewhat 
futureproof. The `int` was simple, straighforward and great. 
These suggestions feel like some `C++` all over again.


Re: Deprecation: foreach: loop index implicitly converted from size_t to int

2024-05-03 Thread user1234 via Digitalmars-d-learn

On Friday, 3 May 2024 at 15:19:13 UTC, user1234 wrote:

On Friday, 3 May 2024 at 14:59:57 UTC, BoQsc wrote:

On Friday, 3 May 2024 at 13:18:02 UTC, user1234 wrote:

[...]





So how would you update this example, what is the right index 
type here to choose?


```
import std.stdio : writefln;

void main() {
auto arr = [
[5, 15],  // 20
[2, 3, 2, 3], // 10
[3, 6, 2, 9], // 20
];

foreach (i, row; arr)
{
double total = 0.0;
foreach (e; row)
total += e;

auto avg = total / row.length;
writefln("AVG [row=%d]: %.2f", i, avg);
}
}
```

Example taken from 
https://tour.dlang.org/tour/en/basics/foreach


Isn't that obvious ?

```d
foreach (const size_t i, row; arr)
```

`arr` is not a static array, it is a dynamic one, consequently 
its `.length` type is `size_t`, even if you have the feeling 
that, in the present situation, `int` bitwidth would be 
sufficient.


even better:

```d
foreach (const typeof(arr.length) i, row; arr)
```

Otherwise I respect your POV, it's just that here I have no 
problem with the way that works. I dont see any issue with the 
type system. D type system is static, strong, but optionally 
inferred. And that's it.


Re: Deprecation: foreach: loop index implicitly converted from size_t to int

2024-05-03 Thread user1234 via Digitalmars-d-learn

On Friday, 3 May 2024 at 14:59:57 UTC, BoQsc wrote:

On Friday, 3 May 2024 at 13:18:02 UTC, user1234 wrote:

On Friday, 3 May 2024 at 10:50:03 UTC, BoQsc wrote:

[...]


**You can specify the index type, just choose the right one.** 
For now there's a deprecation message but after some while 
you'll get a proper error message, e.g _"index type for arr 
must be of type T because arr.length type is T"_.


What's is happening now is to help people updating their code 
and prevent abrupt breakages.





So how would you update this example, what is the right index 
type here to choose?


```
import std.stdio : writefln;

void main() {
auto arr = [
[5, 15],  // 20
[2, 3, 2, 3], // 10
[3, 6, 2, 9], // 20
];

foreach (i, row; arr)
{
double total = 0.0;
foreach (e; row)
total += e;

auto avg = total / row.length;
writefln("AVG [row=%d]: %.2f", i, avg);
}
}
```

Example taken from https://tour.dlang.org/tour/en/basics/foreach


Isn't that obvious ?

```d
foreach (const size_t i, row; arr)
```

`arr` is not a static array, it is a dynamic one, consequently 
its `.length` type is `size_t`, even if you have the feeling 
that, in the present situation, `int` bitwidth would be 
sufficient.


Re: Deprecation: foreach: loop index implicitly converted from size_t to int

2024-05-03 Thread BoQsc via Digitalmars-d-learn

On Friday, 3 May 2024 at 13:18:02 UTC, user1234 wrote:

On Friday, 3 May 2024 at 10:50:03 UTC, BoQsc wrote:
Why am I forced to visit this D Lang thread, why this 
deprecation warning still appears in my console window in the 
latest version of DMD. Does not make any sense from the 
developer's perspective to show this warning and pollute the 
already polluted logging entries of the compiler. How am I 
suppose to program anything effectively if half of the screen 
are some nonsensical deprecation warnings without guidance or 
sane explanations.


This is not better
```
foreach (i, row; arr)
```
than
```
foreach (int i, row; arr)
```
Hides the datatype and makes the D language appear in-explicit 
and annoying.


What is this language becoming. A completely weak typed 
language or something?


I would use JavaScript if I would want that. How are we 
suppose to make whole sane Operating Systems with such 
syntaxes. Do everyone just enjoy having bugs with some 
implicit size_t, or do everyone just enjoy deprecation 
warnings in their logging systems when there are way more 
important problems to solve, that are actually project related.


**You can specify the index type, just choose the right one.** 
For now there's a deprecation message but after some while 
you'll get a proper error message, e.g _"index type for arr 
must be of type T because arr.length type is T"_.


What's is happening now is to help people updating their code 
and prevent abrupt breakages.





So how would you update this example, what is the right index 
type here to choose?


```
import std.stdio : writefln;

void main() {
auto arr = [
[5, 15],  // 20
[2, 3, 2, 3], // 10
[3, 6, 2, 9], // 20
];

foreach (i, row; arr)
{
double total = 0.0;
foreach (e; row)
total += e;

auto avg = total / row.length;
writefln("AVG [row=%d]: %.2f", i, avg);
}
}
```

Example taken from https://tour.dlang.org/tour/en/basics/foreach


Re: Deprecation: foreach: loop index implicitly converted from size_t to int

2024-05-03 Thread user1234 via Digitalmars-d-learn

On Friday, 3 May 2024 at 10:50:03 UTC, BoQsc wrote:
Why am I forced to visit this D Lang thread, why this 
deprecation warning still appears in my console window in the 
latest version of DMD. Does not make any sense from the 
developer's perspective to show this warning and pollute the 
already polluted logging entries of the compiler. How am I 
suppose to program anything effectively if half of the screen 
are some nonsensical deprecation warnings without guidance or 
sane explanations.


This is not better
```
foreach (i, row; arr)
```
than
```
foreach (int i, row; arr)
```
Hides the datatype and makes the D language appear in-explicit 
and annoying.


What is this language becoming. A completely weak typed 
language or something?


I would use JavaScript if I would want that. How are we suppose 
to make whole sane Operating Systems with such syntaxes. Do 
everyone just enjoy having bugs with some implicit size_t, or 
do everyone just enjoy deprecation warnings in their logging 
systems when there are way more important problems to solve, 
that are actually project related.


You can specify the index type, just choose the right one. For 
now there's a deprecation message but after some while you'll get 
a proper error message, e.g _"index type for arr must be of type 
T because arr.length type is T"_.


What's is happening now is to help people updating their code and 
prevent abrupt breakages.


Re: Deprecation: foreach: loop index implicitly converted from size_t to int

2024-05-03 Thread BoQsc via Digitalmars-d-learn
Why am I forced to visit this D Lang thread, why this deprecation 
warning still appears in my console window in the latest version 
of DMD. Does not make any sense from the developer's perspective 
to show this warning and pollute the already polluted logging 
entries of the compiler. How am I suppose to program anything 
effectively if half of the screen are some nonsensical 
deprecation warnings without guidance or sane explanations.


This is not better
```
foreach (i, row; arr)
```
than
```
foreach (int i, row; arr)
```
Hides the datatype and makes the D language appear in-explicit 
and annoying.


What is this language becoming. A completely weak typed language 
or something?


I would use JavaScript if I would want that. How are we suppose 
to make whole sane Operating Systems with such syntaxes. Do 
everyone just enjoy having bugs with some implicit size_t, or do 
everyone just enjoy deprecation warnings in their logging systems 
when there are way more important problems to solve, that are 
actually project related.


Re: is the array literal in a loop stack or heap allocated?

2023-10-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/10/23 10:54 PM, mw wrote:

Hi,

I want to confirm: in the following loop, is the array literal `a` vs. 
`b` stack or heap allocated? and how many times?


ask the compiler:

```d
void main() @nogc {

int[2] a;
int[] b;

int i;
while(++i <=100) {

  a = [i, i+1];  // array literal
  //b = [i, i+1]; // yes, this allocates, had to comment it out

}

}
```

-Steve



Re: is the array literal in a loop stack or heap allocated?

2023-10-10 Thread Imperatorn via Digitalmars-d-learn

On Wednesday, 11 October 2023 at 02:54:53 UTC, mw wrote:

Hi,

I want to confirm: in the following loop, is the array literal 
`a` vs. `b` stack or heap allocated? and how many times?


void main() {

int[2] a;
int[] b;

int i;
While(++i <=100) {

  a = [i, i+1];  // array literal
  b = [i, i+1];

}

}


Thanks.


profile=gc


Re: is the array literal in a loop stack or heap allocated?

2023-10-10 Thread mw via Digitalmars-d-learn

On Wednesday, 11 October 2023 at 03:15:30 UTC, H. S. Teoh wrote:
On Wed, Oct 11, 2023 at 02:54:53AM +, mw via 
Digitalmars-d-learn wrote:

Hi,

I want to confirm: in the following loop, is the array literal 
`a` vs. `b` stack or heap allocated? and how many times?


void main() {

int[2] a;


This is stack-allocated. Once per call to the function.



int[] b;


This is an empty slice. It can refer to either stack or heap 
memory, depending on what's assigned to it.




int i;
While(++i <=100) {

  a = [i, i+1];  // array literal


`a` is overwritten in-place once per loop.


How about the temporary array literal on the right hand side? 
It's stack / heap allocated? Or it's not in the language 
specification, but up to the (optimizing) compiler to decide?





  b = [i, i+1];

[...]

A new array consisting of 2 elements is allocated, once per 
loop, and assigned to b each time. Any arrays from previous 
iterations will be collected by the GC eventually.



T





Re: is the array literal in a loop stack or heap allocated?

2023-10-10 Thread ryuukk_ via Digitalmars-d-learn

On Wednesday, 11 October 2023 at 02:54:53 UTC, mw wrote:

Hi,

I want to confirm: in the following loop, is the array literal 
`a` vs. `b` stack or heap allocated? and how many times?


void main() {

int[2] a;
int[] b;

int i;
While(++i <=100) {

  a = [i, i+1];  // array literal
  b = [i, i+1];

}

}


Thanks.



a is a static array, therefore it won't allocate any, it's a 
memcpy


b will be heap allocated, and it'll do an allocate at each 
iteration



```D
void test_b()
{
int[] a;
int i;
while (++i <= 100)
{
a = [i, i + 1];
printf("%p\n", a.ptr);
}
}
```

You can run this, and it'll print a different address each time


If you add `[]` it'll do range based copy (memcpy), but since the 
array is not initialized, it has a length of 0, so you only need 
to allocate once (either with GC or with malloc)


```D
void test_b()
{
int[] a;
int i;

a.length = 2; // initialize the heap allocated array here

// or with malloc:
// auto ptr = malloc(int.sizeof * 2);
// a = cast(int[]) ptr[0 .. int.sizeof * 2];

while (++i <= 100)
{
a[] = [i, i + 1];
printf("%p\n", a.ptr);
}
}
```

Otherwise you'd get: ``core.exception.RangeError@onlineapp.d(18): 
Range violation``


I don't use D with the GC, so my memory about it is probably 
foggy, but i'm pretty sure what i said is right, please anyone 
correct me if i'm wrong




Re: is the array literal in a loop stack or heap allocated?

2023-10-10 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Oct 11, 2023 at 02:54:53AM +, mw via Digitalmars-d-learn wrote:
> Hi,
> 
> I want to confirm: in the following loop, is the array literal `a` vs.
> `b` stack or heap allocated? and how many times?
> 
> void main() {
> 
> int[2] a;

This is stack-allocated. Once per call to the function.


> int[] b;

This is an empty slice. It can refer to either stack or heap memory,
depending on what's assigned to it.


> int i;
> While(++i <=100) {
> 
>   a = [i, i+1];  // array literal

`a` is overwritten in-place once per loop.


>   b = [i, i+1];
[...]

A new array consisting of 2 elements is allocated, once per loop, and
assigned to b each time. Any arrays from previous iterations will be
collected by the GC eventually.


T

-- 
They pretend to pay us, and we pretend to work. -- Russian saying


is the array literal in a loop stack or heap allocated?

2023-10-10 Thread mw via Digitalmars-d-learn

Hi,

I want to confirm: in the following loop, is the array literal 
`a` vs. `b` stack or heap allocated? and how many times?


void main() {

int[2] a;
int[] b;

int i;
While(++i <=100) {

  a = [i, i+1];  // array literal
  b = [i, i+1];

}

}


Thanks.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-09 Thread bauss via Digitalmars-d-learn

On Monday, 9 January 2023 at 00:19:39 UTC, thebluepandabear wrote:
Fixing this will improve the quality of the language for 
newcomers such as myself greatly.


This not only confuses newcomers but it gave a false illusion 
of a bug within the code :/


It doesn't confuse newcomers only, also people who have used D 
for over a decade like me :) Mostly because it's not a thing in 
most (if not all) other languages.


I think D is unique in that aspect.

It should be fixed however, I don't think the current behavior is 
correct or expected by anyone.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-08 Thread thebluepandabear via Digitalmars-d-learn
: create a copy of the value that is currently present in one 
particular iteration of the `foreach` by creating a function 
literal that takes your `struct` as a paramter. This works 
because structs are value types, so passing it to the function 
creates a copy.


Thanks, your solution seems to be the most elegant one yet, I 
recently came across the similar problem and I realized that the 
other answer was too long and verbose.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-08 Thread thebluepandabear via Digitalmars-d-learn
Fixing this will improve the quality of the language for 
newcomers such as myself greatly.


This not only confuses newcomers but it gave a false illusion of 
a bug within the code :/


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-08 Thread thebluepandabear via Digitalmars-d-learn
A nested function (or perhaps an inline lambda) is needed to 
force the allocation of a dynamic context for the capture.


This is an embarrassment. Why hasn't this been fixed yet? :-(


T


I agree that this needs to get fixed immediately, it seems to be 
bugging me another time as well.


I believe I saw a similar StackOverflow post about this issue for 
C#, and Microsoft did fix it, hopefully D can do the same. Fixing 
this will improve the quality of the language for newcomers such 
as myself greatly.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread Tejas via Digitalmars-d-learn
On Thursday, 5 January 2023 at 22:49:01 UTC, thebluepandabear 
wrote:

Have fun reading this :

https://issues.dlang.org/show_bug.cgi?id=21929


Thanks for the code suggestion although it still doesn't fix 
the bug. I am curious as to what those brackets do as well.


Okay, my bad for writing the wrong code, the correct one is:
```d
 foreach (BoardSize boardSizeIter; arr) (Boardsize boardSize){ // 
notice the brackets and I changed the variable names a little

 Button button = new Button();
 button.text = format("%sx%s", boardSize[0], boardSize[1]);
 button.onButtonClick = {

 eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);
 };
 button.onButtonClick();
 _boardSizeRow.addChild(button);
 }(boardSizeIter) // notice the brackets and that I changed the 
name of you first foreach argument

```

This will do the same thing as HS Teoh and Tsbockman's code did : 
create a copy of the value that is currently present in one 
particular iteration of the `foreach` by creating a function 
literal that takes your `struct` as a paramter. This works 
because structs are value types, so passing it to the function 
creates a copy.




Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 05, 2023 at 10:46:07PM +, thebluepandabear via 
Digitalmars-d-learn wrote:
> On Thursday, 5 January 2023 at 17:36:55 UTC, H. S. Teoh wrote:
[...]
> > ```D
> > foreach (BoardSize boardSize; arr) {
> > Button button = new Button();
> > button.text = format("%sx%s", boardSize[0], boardSize[1]);
> > BoardSize size = boardSize; // force separate capture
> > button.onButtonClick = {
> > eventHandler.settingsWindow_onBoardSizeButtonClick(size);
> > };
> > button.onButtonClick();
> > _boardSizeRow.addChild(button);
> > }
> > ```
[...]
> Your code with the variable capture doesn't seem to work.

Argh, apparently locals inside the loop body are subject to the same
quirky behaviour. >:-(  Here's a workaround that works:

foreach (BoardSize boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", boardSize[0], boardSize[1]);
void wowThisIsDumb(BoardSize size) {
button.onButtonClick = {

eventHandler.settingsWindow_onBoardSizeButtonClick(size);
};
}
wowThisIsDumb(boardSize);
button.onButtonClick();
_boardSizeRow.addChild(button);
}

A nested function (or perhaps an inline lambda) is needed to force the
allocation of a dynamic context for the capture.

This is an embarrassment. Why hasn't this been fixed yet? :-(


T

-- 
Being able to learn is a great learning; being able to unlearn is a greater 
learning.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread thebluepandabear via Digitalmars-d-learn

```

These two solutions should compile to approximately the same 
runtime code, with optimizations enabled. So, it's really down 
to personal preference; the former is more explicit about what 
the computer is to do, while the latter is more concise.


Thanks! Works great.




Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread thebluepandabear via Digitalmars-d-learn

Have fun reading this :

https://issues.dlang.org/show_bug.cgi?id=21929


Thanks for the code suggestion although it still doesn't fix the 
bug. I am curious as to what those brackets do as well.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread thebluepandabear via Digitalmars-d-learn

On Thursday, 5 January 2023 at 17:36:55 UTC, H. S. Teoh wrote:
On Thu, Jan 05, 2023 at 11:55:33AM +, thebluepandabear via 
Digitalmars-d-learn wrote: [...]

```D
foreach (BoardSize boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", boardSize[0], boardSize[1]);
button.onButtonClick = {
eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);
};
button.onButtonClick();
_boardSizeRow.addChild(button);
}
```


This is a classic D trap: the loop variable is only allocated 
once, and the closure captures the single location where the 
loop variable resides, thus every delegate from every loop 
iteration will see the same value when they are run later, 
i.e., the last value of the loop index. Do this instead:


```D
foreach (BoardSize boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", boardSize[0], boardSize[1]);
BoardSize size = boardSize; // force separate capture
button.onButtonClick = {

eventHandler.settingsWindow_onBoardSizeButtonClick(size);

};
button.onButtonClick();
_boardSizeRow.addChild(button);
}
```

This is arguably a language bug (I can't imagine any sane use 
case where somebody would actually want the current semantics). 
 But we have not be successful in convincing Walter about 
this...



T


Your code with the variable capture doesn't seem to work.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 05, 2023 at 11:55:33AM +, thebluepandabear via 
Digitalmars-d-learn wrote:
[...]
> ```D
> foreach (BoardSize boardSize; arr) {
> Button button = new Button();
> button.text = format("%sx%s", boardSize[0], boardSize[1]);
> button.onButtonClick = {
> eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);
> };
> button.onButtonClick();
> _boardSizeRow.addChild(button);
> }
> ```

This is a classic D trap: the loop variable is only allocated once, and
the closure captures the single location where the loop variable
resides, thus every delegate from every loop iteration will see the same
value when they are run later, i.e., the last value of the loop index.
Do this instead:

```D
foreach (BoardSize boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", boardSize[0], boardSize[1]);
BoardSize size = boardSize; // force separate capture
button.onButtonClick = {
eventHandler.settingsWindow_onBoardSizeButtonClick(size);
};
button.onButtonClick();
_boardSizeRow.addChild(button);
}
```

This is arguably a language bug (I can't imagine any sane use case where
somebody would actually want the current semantics).  But we have not be
successful in convincing Walter about this...


T

-- 
Don't throw out the baby with the bathwater. Use your hands...


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread Tejas via Digitalmars-d-learn
On Thursday, 5 January 2023 at 11:55:33 UTC, thebluepandabear 
wrote:
I am using CSFML D bindings and I have created my own sort of 
UI library for drawing elements onto the screen.


One of the classes I've created is a `Button` class, which 
contains a delegate called `onButtonClick` which is called when 
the button is clicked on by the user.


Up until now, everything has worked fine.

I want to add a couple of buttons side by side to represent an 
element of a list and assign them each a unique lambda 
expression for that particular element in the list, this is the 
current code I have:


```D
foreach (BoardSize boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", boardSize[0], boardSize[1]);
button.onButtonClick = {

eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);

};
button.onButtonClick();
_boardSizeRow.addChild(button);
}
```

Running this code, I had expected that everything would work 
fine. Unfortunately upon running the code, tapping each of the 
buttons returned only the largest `boardSize` value, the one 
which is gets iterated last.


Note that I am still not totally sure why this is the case. At 
first, I was confused, but then I suspected that after the 
variable gets sent as a parameter to the 
`settingsWindow_onBoardSizeButtonClick` function, it gets 
changed again in the next iteration creating a sort of chain 
effect -- I may be wrong, but this is my suspicion.


Some of the things I tried was creating a new object each time, 
although it didn't work. I might have not done this properly as 
I am a beginner to D language. I saw someone else ask a similar 
question as to why this is happening but that was for C#, not 
D, so it wasn't that much of a use to me.


Help would be appreciated!


Ah, I think you ran into that delegate bug

# 沈

Try this code in it's place:

```d
 foreach (BoardSize boardSize; arr) (){ // notice the brackets
 Button button = new Button();
 button.text = format("%sx%s", boardSize[0], boardSize[1]);
 button.onButtonClick = {

 eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);
 };
 button.onButtonClick();
 _boardSizeRow.addChild(button);
 }() // notice the brackets
```
This is not your fault, it's an "optimization" that's being 
performed by dmd so that "the user doesn't get surprised" when 
they realize that capturing every single variable emitted in a 
`foreach` will allocate a new heap closure


Have fun reading this :

https://issues.dlang.org/show_bug.cgi?id=21929



Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread tsbockman via Digitalmars-d-learn
On Thursday, 5 January 2023 at 13:05:46 UTC, thebluepandabear 
wrote:
Update some time later: the only way (oof!) around this seems 
to be using a `static foreach` with arrays:


```D
Button[3] b;

static foreach (indx, BoardSize boardSize; arr) {
b[indx] = new Button();
b[indx].text = format("%sx%s", boardSize[0], boardSize[1]);
b[indx].onButtonClick = {

eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);

};
_boardSizeRow.addChild(b[indx]);
}
```


This is semantically equivalent to copying and pasting the loop 
body `arr.length` number of times, substituting the expression 
`arr[indx]` for `boardSize`, and the literal value of `indx` for 
`indx`.


Unlike with a runtime (non-`static`) loop, the event handler 
closure does not capture a reference to `boardSize` or `indx`, 
because they don't actually exist at runtime and so cannot be 
referenced. Instead, `arr.length` different event handler 
functions are created at compile time, with each having the 
appropriate `indx` literal substituted.


So, while it does work as long as `arr.length` is known at 
compile time, it will cause a ton of needless code bloat unless 
`arr.length` is very small.



Any other ways of fixing this annoying issue?


Yes, see [my earlier 
reply](https://forum.dlang.org/post/fwnccjunvnffmtaho...@forum.dlang.org) for an explanation of how to get your original run time loop working as intended.




Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread tsbockman via Digitalmars-d-learn
On Thursday, 5 January 2023 at 11:55:33 UTC, thebluepandabear 
wrote:

```D
foreach (BoardSize boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", boardSize[0], boardSize[1]);
button.onButtonClick = {

eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);

};
button.onButtonClick();
_boardSizeRow.addChild(button);
}
```

Running this code, I had expected that everything would work 
fine. Unfortunately upon running the code, tapping each of the 
buttons returned only the largest `boardSize` value, the one 
which is gets iterated last.


The problem is twofold:

1. Closures in D capture their environment by reference.
2. D (incorrectly, in my opinion) considers loop-local variables 
to have the same identity across each iteration of the loop 
within a single function call.


So, `boardSize` in your event handler is a reference to a single 
variable whose value is overwritten on each iteration of the 
loop. As the event handlers are (I presume) never called until 
after the loop has terminated, the only value they will ever see 
is whichever was set by the final iteration of the loop in that 
function call.


There are at least two possible solutions:

1. Use a `struct` to explicitly capture `boardSize` by value, 
instead of by reference:

```D
static struct ClickHandler {
// If eventHandler is not a global variable of some sort, add 
another field for it:

BoardSize iteration_boardSize;
this(BoardSize iteration_boardSize) {
this.iteration_boardSize = iteration_boardSize;
}

void opCall() {

eventHandler.settingsWindow_onBoardSizeButtonClick(iteration_boardSize);

}
}

foreach (BoardSize loop_boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", loop_boardSize[0], 
loop_boardSize[1]);
button.onButtonClick = &(new 
ClickHandler(loop_boardSize)).opCall;

button.onButtonClick();
_boardSizeRow.addChild(button);
}
```

2. Use a nested function call with a `boardSize` parameter to 
create a copy of `boardSize`  with a unique identity on each 
iteration of the loop:

```D
foreach (BoardSize loop_boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", loop_boardSize[0], 
loop_boardSize[1]);

button.onButtonClick = (BoardSize iteration_boardSize) {
return {

eventHandler.settingsWindow_onBoardSizeButtonClick(iteration_boardSize);

};
}(loop_boardSize);
button.onButtonClick();
_boardSizeRow.addChild(button);
}
```

These two solutions should compile to approximately the same 
runtime code, with optimizations enabled. So, it's really down to 
personal preference; the former is more explicit about what the 
computer is to do, while the latter is more concise.


Re: How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread thebluepandabear via Digitalmars-d-learn



Update some time later: the only way (oof!) around this seems to 
be using a `static foreach` with arrays:


```D
Button[3] b;

static foreach (indx, BoardSize boardSize; arr) {
b[indx] = new Button();
b[indx].text = format("%sx%s", boardSize[0], boardSize[1]);
b[indx].onButtonClick = {

eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);

};
_boardSizeRow.addChild(b[indx]);
}
```

Any other ways of fixing this annoying issue?




How to avoid variable capturing in `foreach` loop with lambdas?

2023-01-05 Thread thebluepandabear via Digitalmars-d-learn
I am using CSFML D bindings and I have created my own sort of UI 
library for drawing elements onto the screen.


One of the classes I've created is a `Button` class, which 
contains a delegate called `onButtonClick` which is called when 
the button is clicked on by the user.


Up until now, everything has worked fine.

I want to add a couple of buttons side by side to represent an 
element of a list and assign them each a unique lambda expression 
for that particular element in the list, this is the current code 
I have:


```D
foreach (BoardSize boardSize; arr) {
Button button = new Button();
button.text = format("%sx%s", boardSize[0], boardSize[1]);
button.onButtonClick = {

eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);

};
button.onButtonClick();
_boardSizeRow.addChild(button);
}
```

Running this code, I had expected that everything would work 
fine. Unfortunately upon running the code, tapping each of the 
buttons returned only the largest `boardSize` value, the one 
which is gets iterated last.


Note that I am still not totally sure why this is the case. At 
first, I was confused, but then I suspected that after the 
variable gets sent as a parameter to the 
`settingsWindow_onBoardSizeButtonClick` function, it gets changed 
again in the next iteration creating a sort of chain effect -- I 
may be wrong, but this is my suspicion.


Some of the things I tried was creating a new object each time, 
although it didn't work. I might have not done this properly as I 
am a beginner to D language. I saw someone else ask a similar 
question as to why this is happening but that was for C#, not D, 
so it wasn't that much of a use to me.


Help would be appreciated!


Re: Disk write in a "for" loop with RwMutex never happens

2022-08-29 Thread rikki cattermole via Digitalmars-d-learn



On 30/08/2022 8:16 AM, Gavin Ray wrote:

It must have been the "writing at end of file" bit?


I don't know.

It read like it should work.

The offsets were correct, it just didn't work *shrug*.


Re: Disk write in a "for" loop with RwMutex never happens

2022-08-29 Thread Gavin Ray via Digitalmars-d-learn

On Monday, 29 August 2022 at 15:52:31 UTC, rikki cattermole wrote:
After a bunch of playing around I managed to determine that it 
is as simple as the mode.


exists(dbFileName) ? "r+" : "w+"



Will fix it.

Of course you shouldn't delete the file like that method is 
doing. It should probably reinitialize the FILE* descriptor.


D'oh!

I didn't even think about the mode:

  > `a+ or ab+ or a+b`
  > "Append; open or create file for update, writing at 
end-of-file."


It must have been the "writing at end of file" bit?

Thanks Rikki. /embarrassed


Re: Disk write in a "for" loop with RwMutex never happens

2022-08-29 Thread ag0aep6g via Digitalmars-d-learn

On Monday, 29 August 2022 at 16:21:53 UTC, ag0aep6g wrote:
You never change `pageId`. So as far as I can tell, you're 
always `seek`-ing to the same position, and you just overwrite 
the same piece of the file again and again.


Whoops. I guess I missed the point of the question there.


Re: Disk write in a "for" loop with RwMutex never happens

2022-08-29 Thread ag0aep6g via Digitalmars-d-learn

On Sunday, 28 August 2022 at 22:46:17 UTC, Gavin Ray wrote:

I've put the code, stripped to a minimal example here:
- https://ldc.godbolt.org/z/fzsx3Tnnn

[...]


But if the same code is placed inside of a `for` loop, suddenly 
no writes occur:

[...]


Does anyone know what is happening here? It's really puzzling.


Relevant pieces of the code:

```d
class DiskManager
{
void writePage(PageId pageId, ubyte[PAGE_SIZE] pageData)
{
synchronized (dbIOMutex.writer)
{
dbFile.seek(pageId * PAGE_SIZE);
dbFile.rawWrite(pageData);
}
}
}

void singleReadWrite()
{
PageId pageId = 0;

diskManager.writePage(pageId, pageData);
}

void multiReadWrite()
{
PageId pageId = 0;

foreach (i; 0 .. 10)
{
diskManager.writePage(pageId, pageData);
}
}
```

You never change `pageId`. So as far as I can tell, you're always 
`seek`-ing to the same position, and you just overwrite the same 
piece of the file again and again.


Re: Disk write in a "for" loop with RwMutex never happens

2022-08-29 Thread rikki cattermole via Digitalmars-d-learn
After a bunch of playing around I managed to determine that it is as 
simple as the mode.


exists(dbFileName) ? "r+" : "w+"



Will fix it.

Of course you shouldn't delete the file like that method is doing. It 
should probably reinitialize the FILE* descriptor.


Re: Disk write in a "for" loop with RwMutex never happens

2022-08-29 Thread Gavin Ray via Digitalmars-d-learn

On Monday, 29 August 2022 at 07:04:49 UTC, bauss wrote:

Does anyone know what is happening here? It's really puzzling.


You probably need to flush the output.


That's a good idea. I gave it a shot, and the following doesn't 
seem to change anything unfortunately:


```d
void writePage(PageId pageId, ubyte[PAGE_SIZE] pageData)
{
synchronized (dbIOMutex.writer)
{
dbFile.seek(pageId * PAGE_SIZE);
dbFile.rawWrite(pageData);
dbFile.flush();
dbFile.sync();
}
}
```


Re: Disk write in a "for" loop with RwMutex never happens

2022-08-29 Thread bauss via Digitalmars-d-learn

On Sunday, 28 August 2022 at 22:46:17 UTC, Gavin Ray wrote:

I've put the code, stripped to a minimal example here:
- https://ldc.godbolt.org/z/fzsx3Tnnn

You can see that the single write + read version of the code 
works just fine:

```
pageData[0..4] = [1, 2, 3, 4]
readData[0..4] = [1, 2, 3, 4]
```

Where here, `pageData` is the data to be written to a file, and 
`readData` is the result of trying to read the freshly written 
file data.


But if the same code is placed inside of a `for` loop, suddenly 
no writes occur:

```d
pageData[0..4] = [0, 0, 0, 0]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 1]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 2]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 3]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 4]
readData[0..4] = [0, 0, 0, 0]

// ...
```

Does anyone know what is happening here? It's really puzzling.


You probably need to flush the output.


Disk write in a "for" loop with RwMutex never happens

2022-08-28 Thread Gavin Ray via Digitalmars-d-learn

I've put the code, stripped to a minimal example here:
- https://ldc.godbolt.org/z/fzsx3Tnnn

You can see that the single write + read version of the code 
works just fine:

```
pageData[0..4] = [1, 2, 3, 4]
readData[0..4] = [1, 2, 3, 4]
```

Where here, `pageData` is the data to be written to a file, and 
`readData` is the result of trying to read the freshly written 
file data.


But if the same code is placed inside of a `for` loop, suddenly 
no writes occur:

```d
pageData[0..4] = [0, 0, 0, 0]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 1]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 2]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 3]
readData[0..4] = [0, 0, 0, 0]

pageData[0..4] = [0, 0, 0, 4]
readData[0..4] = [0, 0, 0, 0]

// ...
```

Does anyone know what is happening here? It's really puzzling.


Re: Main foreach loop fails when another foreach is added

2022-08-07 Thread ikelaiah via Digitalmars-d-learn
On Monday, 8 August 2022 at 02:45:54 UTC, Steven Schveighoffer 
wrote:


And now, you tried to read it again! Which means you are trying 
to read more data from an empty stream.


You need to either a) reopen the file, or b) do both in the 
same loop.



-Steve


Steve! You are Legend!
**Thank you**.
It is obvious now the second `foreach` is reading from an empty 
stream!


Regards,
ikel


Re: Main foreach loop fails when another foreach is added

2022-08-07 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/7/22 10:11 PM, ikelaiah wrote:

Hi,

I'm writing a program that reads a text file and launch my work URLs in it.
It worked fine, and very happy.

Then I added another `foreach` loop to count total number of lines.
After this, the main `foreach` won't work.

Does anyone know as to why this happens?
I might have missed something very obvious.

Thank you.




```d


...


     // Open input file for reading
     size_t line_count = 0;
     File input_file = File(input_filename);


Here you open the file

     auto file_range = input_file.byLine(KeepTerminator.no, 
std.ascii.newline);


And then wrap it in a byline range.



     // if this foreach not commented out
     // the last foreach won't run.
     foreach (char[] line; file_range)
     {
     line_count += 1;
     }


For this foreach loop, you read every line in the file, exhausting the 
file (the input stream for the file is empty).




     // the MAIN foreach loop
     // -- won't run if above foreach is enabled
     foreach (char[] line; file_range)
     {
     if (!line.empty)
     {
     writeln("Open URL: " ~ line);
     Thread.sleep(dur!("seconds")(2));
     browse(line);
     }
     }


And now, you tried to read it again! Which means you are trying to read 
more data from an empty stream.


You need to either a) reopen the file, or b) do both in the same loop.


```


-Steve


Main foreach loop fails when another foreach is added

2022-08-07 Thread ikelaiah via Digitalmars-d-learn

Hi,

I'm writing a program that reads a text file and launch my work 
URLs in it.

It worked fine, and very happy.

Then I added another `foreach` loop to count total number of 
lines.

After this, the main `foreach` won't work.

Does anyone know as to why this happens?
I might have missed something very obvious.

Thank you.

Regards,
ikel


```d
module openurls;

import std.stdio : writeln, File, KeepTerminator;
import std.file;
import std.range;
import std.ascii;
import std.getopt : getopt, GetoptResult, defaultGetoptPrinter;
import std.process : browse;
import core.thread.osthread;
import core.time;


void main(string[] args)
{
string input_filename = "";

// Get command line option
GetoptResult user_args = getopt(args,
"input|i", "A list of URLs separated by new lines.", 
_filename);


// Does user need help?
if (user_args.helpWanted)
{
defaultGetoptPrinter("Command line options for Open 
URLs.",

user_args.options);
}

// Is input file specified?
if (input_filename.length == 0)
{
writeln("Open URL: No file specified.\n");
defaultGetoptPrinter("Command line option for Open URLs.",
user_args.options);
return;
}

// Does the file exist?
if (!input_filename.exists)
{
writeln("Open URL: input file --" ~ input_filename ~ "-- 
does not exist.\n");

return;
}
else
{
writeln("Open URL: reading --" ~ input_filename ~ "--");
}

// Open input file for reading
size_t line_count = 0;
File input_file = File(input_filename);
auto file_range = input_file.byLine(KeepTerminator.no, 
std.ascii.newline);


// if this foreach not commented out
// the last foreach won't run.
foreach (char[] line; file_range)
{
line_count += 1;
}

// the MAIN foreach loop
// -- won't run if above foreach is enabled
foreach (char[] line; file_range)
{
if (!line.empty)
{
writeln("Open URL: " ~ line);
Thread.sleep(dur!("seconds")(2));
browse(line);
}
}

writeln("Open URL: completed");

writeln("Closing " ~ input_filename);
input_file.close();
}

```


Re: vectorization of a simple loop -- not in DMD?

2022-07-14 Thread max haughton via Digitalmars-d-learn

On Thursday, 14 July 2022 at 13:00:24 UTC, ryuukk_ wrote:
On Thursday, 14 July 2022 at 05:30:58 UTC, Siarhei Siamashka 
wrote:

On Tuesday, 12 July 2022 at 13:23:36 UTC, ryuukk_ wrote:
I wonder if DMD/LDC/GDC have built in tools to profile and 
track performance


Linux has a decent system wide profiler: 
https://perf.wiki.kernel.org/index.php/Main_Page
And there are other useful tools, such as callgrind. To take 
advantage of all these tools, DMD/LDC/GDC only need to provide 
debugging symbols in the generated binaries, which they 
already do. Profiling applications to identify performance 
bottlenecks is very easy nowadays.


I am not talking about linux, and i am not talking about 3rd 
party tools


I am talking about the developers of DMD/LDC/GDC, do they 
profile the compilers, do they provide ways to monitor/track 
performance? do they benchmark specific parts of the compilers?


I am not talking about the output of valgrind

Zig also has: https://ziglang.org/perf/ (very slow to load)

Having such thing is more useful than being able to plug 
valgrind god knows how into the compiler and try to decipher 
what does what and what results correspond to what internally, 
and what about a graph over time to catch regressions?


DMD is very fast at compiling code, so i guess Walter doing 
enough work to monitor all of that


LDC on the other hand.. they'd benefit a lot by having such 
thing in place


Running valgrind on the compiler is completely trivial. Builtin 
profilers are often terrible. LDC and GDC and dmd all have 
instrumenting profilers builtin, of varying quality. gprof in 
particular is somewhat infamous.


dmd isn't particularly fast, it does a lot of unnecessary work. 
LDC is slow because LLVM is slow.


We need a graph over time, yes.


Re: vectorization of a simple loop -- not in DMD?

2022-07-14 Thread ryuukk_ via Digitalmars-d-learn
On Thursday, 14 July 2022 at 05:30:58 UTC, Siarhei Siamashka 
wrote:

On Tuesday, 12 July 2022 at 13:23:36 UTC, ryuukk_ wrote:
I wonder if DMD/LDC/GDC have built in tools to profile and 
track performance


Linux has a decent system wide profiler: 
https://perf.wiki.kernel.org/index.php/Main_Page
And there are other useful tools, such as callgrind. To take 
advantage of all these tools, DMD/LDC/GDC only need to provide 
debugging symbols in the generated binaries, which they already 
do. Profiling applications to identify performance bottlenecks 
is very easy nowadays.


I am not talking about linux, and i am not talking about 3rd 
party tools


I am talking about the developers of DMD/LDC/GDC, do they profile 
the compilers, do they provide ways to monitor/track performance? 
do they benchmark specific parts of the compilers?


I am not talking about the output of valgrind

Zig also has: https://ziglang.org/perf/ (very slow to load)

Having such thing is more useful than being able to plug valgrind 
god knows how into the compiler and try to decipher what does 
what and what results correspond to what internally, and what 
about a graph over time to catch regressions?


DMD is very fast at compiling code, so i guess Walter doing 
enough work to monitor all of that


LDC on the other hand.. they'd benefit a lot by having such thing 
in place





Re: vectorization of a simple loop -- not in DMD?

2022-07-14 Thread z via Digitalmars-d-learn

On Monday, 11 July 2022 at 18:15:16 UTC, Ivan Kazmenko wrote:

Hi.

I'm looking at the compiler output of DMD (-O -release), LDC 
(-O -release), and GDC (-O3) for a simple array operation:


```
void add1 (int [] a)
{
foreach (i; 0..a.length)
a[i] += 1;
}
```

Here are the outputs: https://godbolt.org/z/GcznbjEaf

From what I gather at the view linked above, DMD does not use 
XMM registers for speedup, and does not unroll the loop either. 
 Switching between 32bit and 64bit doesn't help either.  
However, I recall in the past it was capable of at least some 
of these optimizations.  So, how do I enable them for such a 
function?


Ivan Kazmenko.


No, not in DMD. DMD generates what looks like 32 bit code adapted 
to x86_64.
LDC may optimize this kind of loop with a tri-way branch 
depending on how many array elements remain. but it can both 
generate very good loop code(particularly when AVX-512 is 
available and the struct/data arrangement in memory is 
unfavorable for SIMD) and very questionable code.
You may be losing performance for obscure reasons that look like 
gnomes decided to steal your precious cpu cycles and when that 
happens there is no way to fix it other than manually going in 
with a disassembler/debugger, changing defect optimizations in 
hot code paths to something faster then save back to executable 
file.(yikes, i know.)


Re: vectorization of a simple loop -- not in DMD?

2022-07-13 Thread Siarhei Siamashka via Digitalmars-d-learn

On Tuesday, 12 July 2022 at 13:23:36 UTC, ryuukk_ wrote:
I wonder if DMD/LDC/GDC have built in tools to profile and 
track performance


Linux has a decent system wide profiler: 
https://perf.wiki.kernel.org/index.php/Main_Page
And there are other useful tools, such as callgrind. To take 
advantage of all these tools, DMD/LDC/GDC only need to provide 
debugging symbols in the generated binaries, which they already 
do. Profiling applications to identify performance bottlenecks is 
very easy nowadays.



Rust have this: https://perf.rust-lang.org/

Maybe we need to do something similar


What is this website? Are they tracking performance differences 
between different versions of Rust or something? Like ensuring 
that the compile time does not regress without them noticing this 
immediately?


Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread ryuukk_ via Digitalmars-d-learn

On Tuesday, 12 July 2022 at 12:47:26 UTC, bauss wrote:
Of course if you're alone it doesn't matter, but if it's a 
larger project that will have multiple maintainers then it will 
never work and will tarnish the project entirely.


That's true, i work solo on my project so it doesn't bother me

It definitely is something hard to balance

But one sure thing is that's something you have to monitor every 
so often, if you don't, then you end up with poor build speed 
that's harder to fix


I wonder if DMD/LDC/GDC have built in tools to profile and track 
performance


Rust have this: https://perf.rust-lang.org/

Maybe we need to do something similar



Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread bachmeier via Digitalmars-d-learn

On Monday, 11 July 2022 at 21:46:10 UTC, IGotD- wrote:

Just depreciate the the DMD backend, it's just not up to the 
task anymore.


Just deprecate LDC and GDC. They compile slowly and are unlikely 
to ever deliver fast compile times, due to their design.


Some people say they like it because it is fast, yes it is fast 
because it doesn't do much.


If it produces code that's fast enough, there is zero benefit to 
using a different compiler. If you use a development workflow 
that's heavy on compilation, stay away from LDC or GDC until 
you're done - and even then, you might not have any motivation to 
use either.


Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread bauss via Digitalmars-d-learn

On Tuesday, 12 July 2022 at 10:32:36 UTC, ryuukk_ wrote:
How do i achieve fast compile speed (results above were on 
windows, on linux i get much faster results):


I maintain healthy project management:



This



- Imports of std: i simply don't, and i copy/paste functions i 
need


- I avoid dub packages, instead i prefer import/src path, and i 
chery pick what i need


And this.

Can be argued to not be healthy project management.

Of course if you're alone it doesn't matter, but if it's a larger 
project that will have multiple maintainers then it will never 
work and will tarnish the project entirely.


Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread ryuukk_ via Digitalmars-d-learn
How do i achieve fast compile speed (results above were on 
windows, on linux i get much faster results):


I maintain healthy project management:

- Templates ONLY when necessary and when the cost is worth the 
time saved in the long term
  - this is why i try to lobby for builtin tagged union instead 
of std.sumtype


- Dependencies, only dependency WITHOUT dependencies, and i keep 
them at the bare minimum!


- Imports of std: i simply don't, and i copy/paste functions i 
need


- I avoid dub packages, instead i prefer import/src path, and i 
chery pick what i need




Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread Siarhei Siamashka via Digitalmars-d-learn

On Tuesday, 12 July 2022 at 07:58:44 UTC, bauss wrote:

You don't think this difference is huge? DMD is over 2x as fast.


I think that DMD having more than 10x faster compilation speed in 
ryuukk_'s project shows that there is likely either a 
misconfiguration in DUB build setup or some other low hanging 
fruit for LDC. This looks like an opportunity to easily improve 
something in a major way.


Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread bauss via Digitalmars-d-learn

On Tuesday, 12 July 2022 at 07:06:37 UTC, Siarhei Siamashka wrote:


```

real0m34.371s
user0m32.883s
sys 0m1.488s
```
```

real0m14.078s
user0m12.941s
sys 0m1.129s

```

Is there an open source DUB package, which can be used to 
reproduce a huge build time difference between LDC and DMD?


You don't think this difference is huge? DMD is over 2x as fast.


Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread Siarhei Siamashka via Digitalmars-d-learn

On Monday, 11 July 2022 at 22:16:05 UTC, ryuukk_ wrote:

LDC clean full rebuild
```
$ time dub build -f --compiler=ldc2
Performing "debug" build using ldc2 for x86_64.
game ~master: building configuration "desktop"...
Linking...

real0m18.033s
user0m0.000s
sys 0m0.015s
```

DMD clean full rebuild
```
$ time dub build -f --compiler=dmd
Performing "debug" build using dmd for x86_64.
game ~master: building configuration "desktop"...
Linking...

real0m1.348s
user0m0.031s
sys 0m0.015s
```


BTW, I'm very curious about investigating the reason for such 
huge build time difference, but can't reproduce it on my 
computer. For example, compiling the DUB source code itself via 
the same DUB commands only results in DMD showing roughly twice 
faster build times (which is great, but nowhere close to ~13x 
difference):


```
$ git clone https://github.com/dlang/dub.git
$ cd dub
```
```
$ time dub build -f --compiler=ldc2
Performing "debug" build using ldc2 for x86_64.
dub 1.29.1+commit.38.g7f6f024f: building configuration 
"application"...
Serializing composite type Flags!(BuildRequirement) which has no 
serializable fields
Serializing composite type Flags!(BuildOption) which has no 
serializable fields

Linking...

real0m34.371s
user0m32.883s
sys 0m1.488s
```
```
$ time dub build -f --compiler=dmd
Performing "debug" build using dmd for x86_64.
dub 1.29.1+commit.38.g7f6f024f: building configuration 
"application"...
Serializing composite type Flags!(BuildRequirement) which has no 
serializable fields
Serializing composite type Flags!(BuildOption) which has no 
serializable fields

Linking...

real0m14.078s
user0m12.941s
sys 0m1.129s

```

Is there an open source DUB package, which can be used to 
reproduce a huge build time difference between LDC and DMD?


Re: vectorization of a simple loop -- not in DMD?

2022-07-12 Thread Siarhei Siamashka via Digitalmars-d-learn

On Monday, 11 July 2022 at 22:16:05 UTC, ryuukk_ wrote:
I use D because DMD compiles my huge project in ~1 second (full 
clean rebuild)


It is a competitive advantage that many languages doesn't have


The other programming languages typically use an interpreter for 
quick iterations and rapid development. For example, Python 
programming language has CPython interpreter, PyPy Just-in-Time 
compiler and Cython optimizing static compiler (not perfect right 
now, but shows a lot of promise).


D still has a certain advantage over interpreters, because DMD 
generated code is typically only up to twice slower than LDC 
generated code. If the x86 architecture stops being dominant in 
the future and gets displaced by ARM or RISC-V, then this may 
become a problem for DMD. But we'll cross that bridge when we get 
there.




Re: vectorization of a simple loop -- not in DMD?

2022-07-11 Thread ryuukk_ via Digitalmars-d-learn

On Monday, 11 July 2022 at 21:46:10 UTC, IGotD- wrote:

On Monday, 11 July 2022 at 18:19:41 UTC, max haughton wrote:


The dmd backend is ancient, it isn't really capable of these 
kinds of loop optimizations.


I've said it several times before. Just depreciate the the DMD 
backend, it's just not up to the task anymore. This is not 
criticism against the original purpose of it as back in the 90s 
and early 2000s it made sense to create your own backend. Time 
has moved on and we have LLVM and GCC backends with a lot of 
CPU support that the D project could never achieve themselves. 
The D project should just can the DMD backend in order to free 
up resources for more important tasks.


Some people say they like it because it is fast, yes it is fast 
because it doesn't do much.


I use D because DMD compiles my huge project in ~1 second (full 
clean rebuild)


It is a competitive advantage that many languages doesn't have


LDC clean full rebuild
```
$ time dub build -f --compiler=ldc2
Performing "debug" build using ldc2 for x86_64.
game ~master: building configuration "desktop"...
Linking...

real0m18.033s
user0m0.000s
sys 0m0.015s
```

LDC incremental
```
$ time dub build --compiler=ldc2
Performing "debug" build using ldc2 for x86_64.
game ~master: building configuration "desktop"...
Linking...

real0m17.215s
user0m0.000s
sys 0m0.000s
```

DMD clean full rebuild
```
$ time dub build -f --compiler=dmd
Performing "debug" build using dmd for x86_64.
game ~master: building configuration "desktop"...
Linking...

real0m1.348s
user0m0.031s
sys 0m0.015s
```

DMD incremental
```
$ time dub build --compiler=dmd
Performing "debug" build using dmd for x86_64.
game ~master: building configuration "desktop"...
Linking...

real0m1.249s
user0m0.000s
sys 0m0.000s
```


The day DMD gets removed is the day i will good a different 
language


I want to thank Walter for maintaining DMD the compiler, and 
making it incredibly fast at compiling code


Release perf can't beat LLVM and its amount of optimizations, but 
the advantage is it allows VERY FAST and QUICK iteration time, it 
is ESSENTIAL for developing software





Re: vectorization of a simple loop -- not in DMD?

2022-07-11 Thread IGotD- via Digitalmars-d-learn

On Monday, 11 July 2022 at 18:19:41 UTC, max haughton wrote:


The dmd backend is ancient, it isn't really capable of these 
kinds of loop optimizations.


I've said it several times before. Just depreciate the the DMD 
backend, it's just not up to the task anymore. This is not 
criticism against the original purpose of it as back in the 90s 
and early 2000s it made sense to create your own backend. Time 
has moved on and we have LLVM and GCC backends with a lot of CPU 
support that the D project could never achieve themselves. The D 
project should just can the DMD backend in order to free up 
resources for more important tasks.


Some people say they like it because it is fast, yes it is fast 
because it doesn't do much.


Re: vectorization of a simple loop -- not in DMD?

2022-07-11 Thread Bruce Carneal via Digitalmars-d-learn

On Monday, 11 July 2022 at 18:15:16 UTC, Ivan Kazmenko wrote:

Hi.

I'm looking at the compiler output of DMD (-O -release), LDC 
(-O -release), and GDC (-O3) for a simple array operation:


```
void add1 (int [] a)
{
foreach (i; 0..a.length)
a[i] += 1;
}
```

Here are the outputs: https://godbolt.org/z/GcznbjEaf

From what I gather at the view linked above, DMD does not use 
XMM registers for speedup, and does not unroll the loop either.

[snip]

Specifying a SIMD capable target will reveal an even wider gap in 
capability.  (LDC -mcpu=x86-64-v3  or gdc -march=x86-64-v3).





Re: vectorization of a simple loop -- not in DMD?

2022-07-11 Thread max haughton via Digitalmars-d-learn

On Monday, 11 July 2022 at 18:15:16 UTC, Ivan Kazmenko wrote:

Hi.

I'm looking at the compiler output of DMD (-O -release), LDC 
(-O -release), and GDC (-O3) for a simple array operation:


```
void add1 (int [] a)
{
foreach (i; 0..a.length)
a[i] += 1;
}
```

Here are the outputs: https://godbolt.org/z/GcznbjEaf

From what I gather at the view linked above, DMD does not use 
XMM registers for speedup, and does not unroll the loop either. 
 Switching between 32bit and 64bit doesn't help either.  
However, I recall in the past it was capable of at least some 
of these optimizations.  So, how do I enable them for such a 
function?


Ivan Kazmenko.


How long ago is the past? The godbolt.org dmd is quite old.

The dmd backend is ancient, it isn't really capable of these 
kinds of loop optimizations.


vectorization of a simple loop -- not in DMD?

2022-07-11 Thread Ivan Kazmenko via Digitalmars-d-learn

Hi.

I'm looking at the compiler output of DMD (-O -release), LDC (-O 
-release), and GDC (-O3) for a simple array operation:


```
void add1 (int [] a)
{
foreach (i; 0..a.length)
a[i] += 1;
}
```

Here are the outputs: https://godbolt.org/z/GcznbjEaf

From what I gather at the view linked above, DMD does not use XMM 
registers for speedup, and does not unroll the loop either.  
Switching between 32bit and 64bit doesn't help either.  However, 
I recall in the past it was capable of at least some of these 
optimizations.  So, how do I enable them for such a function?


Ivan Kazmenko.



Re: vibe.d requestHTTP in static this causes infinite loop?

2022-05-20 Thread Vijay Nayar via Digitalmars-d-learn

On Friday, 20 May 2022 at 01:41:59 UTC, Ali Çehreli wrote:

On 5/19/22 16:44, Vijay Nayar wrote:

> If I remove the call from `static this()`, then the web call
works as
> normal. Any idea why calling vibe.d's `requestHTTP` function
inside of a
> module's static construction would cause an infinite loop?

I am not experienced with vibe.d.

'static this' is executed per thread. If requestHTTP starts a 
new thread, then I can see how you would be in an infinite 
loop. I wonder whether it should be 'shared static this' (which 
is executed once per program, not per thread).


Ali


Very clever, you were exactly right. I had not thought of that, 
but that is indeed what was happening.


Re: vibe.d requestHTTP in static this causes infinite loop?

2022-05-20 Thread bauss via Digitalmars-d-learn

On Friday, 20 May 2022 at 01:41:59 UTC, Ali Çehreli wrote:

On 5/19/22 16:44, Vijay Nayar wrote:

> If I remove the call from `static this()`, then the web call
works as
> normal. Any idea why calling vibe.d's `requestHTTP` function
inside of a
> module's static construction would cause an infinite loop?

I am not experienced with vibe.d.

'static this' is executed per thread. If requestHTTP starts a 
new thread, then I can see how you would be in an infinite 
loop. I wonder whether it should be 'shared static this' (which 
is executed once per program, not per thread).


Ali


Static constructor shouldn't be there at all in this case, since 
it's not constructing anything.


He shouldn't really use anything but main in this case.


Re: vibe.d requestHTTP in static this causes infinite loop?

2022-05-19 Thread Ali Çehreli via Digitalmars-d-learn

On 5/19/22 16:44, Vijay Nayar wrote:

> If I remove the call from `static this()`, then the web call works as
> normal. Any idea why calling vibe.d's `requestHTTP` function inside of a
> module's static construction would cause an infinite loop?

I am not experienced with vibe.d.

'static this' is executed per thread. If requestHTTP starts a new 
thread, then I can see how you would be in an infinite loop. I wonder 
whether it should be 'shared static this' (which is executed once per 
program, not per thread).


Ali



vibe.d requestHTTP in static this causes infinite loop?

2022-05-19 Thread Vijay Nayar via Digitalmars-d-learn
I've encountered an unusual behavior that I have no good 
explanation for. Consider the following code example:


```d
import vibe.core.log : logInfo;
import vibe.http.client : requestHTTP, HTTPClientRequest, 
HTTPClientResponse;

import vibe.http.common : HTTPMethod;
import vibe.stream.operations : readAllUTF8;

void doThing() {
  requestHTTP("http://example.com/;,
  (scope HTTPClientRequest req) {
logInfo("Setting request method.");
req.method = HTTPMethod.GET;
  },
  (scope HTTPClientResponse res) {
logInfo("Log point 1");
string data = res.bodyReader.readAllUTF8();
logInfo("Log point 2: %s", data);
  });
}

static this() {
  logInfo("--- static this() ---");
  doThing();
}

void main(string[] args) {
  logInfo("--- main() ---");
  doThing();
}
```

The output of this program is actually an infinite loop with 
output of the form:

```
[Eventcore DNS Lookup() INF] --- static this() ---
[Eventcore DNS Lookup() INF] --- static this() ---
```

If I remove the call from `static this()`, then the web call 
works as normal. Any idea why calling vibe.d's `requestHTTP` 
function inside of a module's static construction would cause an 
infinite loop?


Re: While loop on global variable optimised away?

2022-05-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 10:01:18 UTC, Johan wrote:
Any function call (inside the loop) for which it cannot be 
proven that it never modifies your memory variable will work. 
That's why I'm pretty sure that mutex lock/unlock will work.


 I think the common semantics ought to be that everything written 
by thread A  before it releases the mutex will be visible to 
thread B when it aquires the same mutex, and any assumptions 
beyond this are nonportable?




Re: While loop on global variable optimised away?

2022-05-11 Thread ichneumwn via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 10:01:18 UTC, Johan wrote:

Any function call (inside the loop) for which it cannot be 
proven that it never modifies your memory variable will work. 
That's why I'm pretty sure that mutex lock/unlock will work.


Thank you, in C I would not have been surprised. It was the 
default thread local storage that made me question it. Your 
remark about the mutex lock/unlock is very helpful, I was 
starting to get worried I would need to keep a very careful watch 
on those __gshareds [well, more than usual :) ]




Re: While loop on global variable optimised away?

2022-05-11 Thread Johan via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 09:34:20 UTC, ichneumwn wrote:

Hi Forum,

I have a snippet of code as follows:
```
extern(C) extern __gshared uint g_count;

// inside a class member function:
  while(g_count) <= count) {}
```

This is from a first draft of the code without proper thread 
synchronisation. The global variable g_count is updated from a 
bit of C++ code. As soon as I turn the optimiser on, the code 
never gets passed this point, leading me to suspect it gets 
turned into

```
  while(true) {}
```

If modify the code in the following way:

```
  import core.volatile : volatileLoad;

  while(volatileLoad(_count) <= count) {}
```

it works again.

My question is, have I hit a compiler bug (ldc 1.28.1, aarch64 
[Raspberry Pi]) or is this part of the language design. I would 
have thought since D use thread-local storage by default, that 
for a __gshared variable it would be understood that it can get 
modified by another thread.


This is part of the language spec. The language assumes that 
there is a single thread running, and any thread synchronization 
must be done by the user. This is well known from C and C++, from 
which D (implicitly afaik) borrows the memory model.


Example: imagine loading a struct with 2 ulongs from shared 
memory: `auto s = global_struct_variable;`. Loading the data into 
local storage `s` - e.g. CPU registers - would happen in two 
steps, first member1, then member2 (simplified, let's assume it 
spans across a cache boundary, etc..). During that load sequence, 
another thread might write to the struct. If the language must 
have defined behavior in that situation (other thread write), 
then a global mutex lock/unlock must be done before/after _every_ 
read and write of shared data. That'd be a big performance impact 
on multithreading. Instead, single-thread execution is assumed, 
and thus the optimization is valid.


Your solution with `volatileLoad` is correct.

Access through atomic function would prevent the compiler from 
optimising this away as well, but if I were to use a Mutex 
inside the loop, there is no way for the compiler to tell 
*what* that Mutex is protecting and it might still decide to 
optimise the test away (assuming that is what is happening, did 
not attempt to look at the assembler code).


Any function call (inside the loop) for which it cannot be proven 
that it never modifies your memory variable will work. That's why 
I'm pretty sure that mutex lock/unlock will work.



On Wednesday, 11 May 2022 at 09:37:26 UTC, rikki cattermole wrote:
Compiler optimizations should not be defined by a programming 
language specification.


This is not true. Compiler optimizations are valid if and only if 
they can be proven by the programming language specification. A 
compiler optimization can never change valid program behavior. If 
an optimization does change behavior, then either the program is 
invalid per the language spec, or the optimization is bugged (or 
the observed behavior change is outside the language spec, such 
as how long a program takes to execute).



-Johan




Re: While loop on global variable optimised away?

2022-05-11 Thread rikki cattermole via Digitalmars-d-learn
Compiler optimizations should not be defined by a programming language 
specification.


This will be on LLVM.


While loop on global variable optimised away?

2022-05-11 Thread ichneumwn via Digitalmars-d-learn

Hi Forum,

I have a snippet of code as follows:
```
extern(C) extern __gshared uint g_count;

// inside a class member function:
  while(g_count) <= count) {}
```

This is from a first draft of the code without proper thread 
synchronisation. The global variable g_count is updated from a 
bit of C++ code. As soon as I turn the optimiser on, the code 
never gets passed this point, leading me to suspect it gets 
turned into

```
  while(true) {}
```

If modify the code in the following way:

```
  import core.volatile : volatileLoad;

  while(volatileLoad(_count) <= count) {}
```

it works again.

My question is, have I hit a compiler bug (ldc 1.28.1, aarch64 
[Raspberry Pi]) or is this part of the language design. I would 
have thought since D use thread-local storage by default, that 
for a __gshared variable it would be understood that it can get 
modified by another thread. Access through atomic function would 
prevent the compiler from optimising this away as well, but if I 
were to use a Mutex inside the loop, there is no way for the 
compiler to tell *what* that Mutex is protecting and it might 
still decide to optimise the test away (assuming that is what is 
happening, did not attempt to look at the assembler code).


Cheers



Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn

On Thursday, 20 January 2022 at 01:14:51 UTC, Adam Ruppe wrote:
On Thursday, 20 January 2022 at 00:55:33 UTC, Jack Stouffer 
wrote:
static foreach(member; __traits(allMembers, 
Manager))


member here is a string, not the member. I prefer to call it 
memberName.


Then you __traits(getMember, Manager, memberName) to actually 
get the alias you can pass to getAttributes.


Thanks, that fixed it. Final working version for anyone who finds 
this thread:


```d
import std.traits;
import std.stdio;

enum Runnable;

struct SubSystem
{
void run()
{
writeln("SubSystem ran");
}
}

struct Manager
{
@Runnable SubSystem subsystem;

void run()
{
static foreach(memberName; __traits(allMembers, Manager))
{
static foreach (attribute; __traits(getAttributes, 
__traits(getMember, Manager, memberName)))

{
static if (is(attribute == Runnable))
{
__traits(getMember, Manager, 
memberName).run();

}
}
}
}
}


void main()
{
Manager m;
m.run();
}
```


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Adam Ruppe via Digitalmars-d-learn

On Thursday, 20 January 2022 at 00:55:33 UTC, Jack Stouffer wrote:
static foreach(member; __traits(allMembers, 
Manager))


member here is a string, not the member. I prefer to call it 
memberName.


Then you __traits(getMember, Manager, memberName) to actually get 
the alias you can pass to getAttributes.


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 21:49:12 UTC, Adam D Ruppe wrote:
I never use most of std.traits, they just complicate things. 
Bleh idk, I wouldn't bother with it and loop through the 
__traits instead.


Unless I'm missing something obvious this has to be a DMD bug, 
because this prints nothing:


```d
import std.traits;
import std.stdio;

enum Runnable;

struct SubSystem
{
void run()
{
writeln("SubSystem ran");
}
}

struct Manager
{
@Runnable SubSystem subsystem;

void run()
{
static foreach(member; __traits(allMembers, Manager))
{
static foreach (attribute; 
__traits(getAttributes, member))

{
static if (attribute == Runnable)
{
__traits(child, Manager, member).run();
}
}
}
}
}

void main()
{
Manager m;
m.run();
}
```

The `__traits(getAttributes, member)` call always returns an 
empty tuple. Calling `__traits(getAttributes, Manager.subsystem)` 
manually works as expected.


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Adam D Ruppe via Digitalmars-d-learn
On Wednesday, 19 January 2022 at 21:44:57 UTC, Jack Stouffer 
wrote:
The error is actually coming from trying to use the result of 
getSymbolsByUDA in the right part of the `static foreach`


huh..

I never use most of std.traits, they just complicate things. Bleh 
idk, I wouldn't bother with it and loop through the __traits 
instead.




Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn

On Wednesday, 19 January 2022 at 20:53:29 UTC, Adam D Ruppe wrote:
So you want to `__traits(child, system, this).run()` and it 
should work - the traits child will re-attach a this value.


The error is actually coming from trying to use the result of 
getSymbolsByUDA in the right part of the `static foreach`, not 
the call to the `run` function. Which was odd to me because I 
thought it just returned a `AliasSeq`.


Here's a link to the erroring code with your traits change:

https://run.dlang.io/is/gO84ox


Re: Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Adam D Ruppe via Digitalmars-d-learn
On Wednesday, 19 January 2022 at 20:46:17 UTC, Jack Stouffer 
wrote:
static foreach(system; getSymbolsByUDA!(Manager, 
Runnable))

{
system.run();
onlineapp.d(16): Error: value of `this` is not known at compile 
time


The getSymbols returns aliases, meaning you hit what I wrote 
about a few days ago:


http://dpldocs.info/this-week-in-d/Blog.Posted_2022_01_10.html#tip-of-the-week

The `this` is a runtime value and all the other `static` things 
work on compile time info.


So you want to `__traits(child, system, this).run()` and it 
should work - the traits child will re-attach a this value.


Using getSymbolsByUDA in a static foreach loop

2022-01-19 Thread Jack Stouffer via Digitalmars-d-learn
I'm trying to use getSymbolsByUDA in order to loop over all of 
the members in a struct with a certain UDA, and then call a 
function on the member. The plan is to use this to avoid looping 
over an array of function pointers.


However, the compiler is giving a strange error and the 
documentation of getSymbolsByUDA is unhelpful, as there are no 
practical use-case examples.


Here's a very simplified version of my code

```d
import std.traits;

enum Runnable;

struct SubSystem
{
void run();
}

struct Manager
{
@Runnable SubSystem subsystem;

void run()
{
static foreach(system; getSymbolsByUDA!(Manager, 
Runnable))

{
system.run();
}
}
}

void main()
{
Manager m;
m.run();
}

```

Result:

```
onlineapp.d(16): Error: value of `this` is not known at compile 
time

```

This seems to me to be the logical way to write this code. What 
am I missing?




Re: How to loop through characters of a string in D language?

2021-12-23 Thread Salih Dincer via Digitalmars-d-learn
On Thursday, 23 December 2021 at 16:13:49 UTC, Stanislav Blinov 
wrote:


You're comparing apples and oranges.
When benchmarking, at least look at
the generated assembly first.

I looked now and you're right. Insomuch that it should be 
eggplant not apple, banana not orange...:)


Because it's an irrelevant benchmarking!

Thank you all...


Re: How to loop through characters of a string in D language?

2021-12-23 Thread rumbu via Digitalmars-d-learn

On Thursday, 23 December 2021 at 07:14:35 UTC, Salih Dincer wrote:

It seems faster than algorithms in Phobos. We would love to see 
this in our new Phobos.



Replace: 436 msecs
Malloc : 259 msecs
*/


It seems because MallocReplace is cheating a lot:
- it is not called through another function like replace is 
called;

- accesses directly the constant str;
- assumes that it has a single character to replace;
- assumes that the character will be deleted not replaced with 
something;

- assumes that the character is always ';'
- assumes that the replacing string is not bigger than the 
replaced one, so it knows exactly how much space to allocate;
- does not have any parameter, at least on x86 this means that 
there is no arg pushes when it's called.
- does not return a string, just compares its result with another 
constant;


Since we already know all this stuff, we can go further :)

```d
string superFast()
{
enum r = str.replace(";", "");
return r;
}

```

Replace: 436 msecs
Malloc : 259 msecs
SuperFast: 0 msecs





Re: How to loop through characters of a string in D language?

2021-12-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 23 December 2021 at 07:14:35 UTC, Salih Dincer wrote:

It seems faster than algorithms in Phobos. We would love to see 
this in our new Phobos.


```d
  void mallocReplace()



  void normalReplace()
string result = str.replace(';',"");

}/* Console Out:
Replace: 436 msecs
Malloc : 259 msecs
*/
```


You're comparing apples and oranges. When benchmarking, at least 
look at the generated assembly first.


replace is not in Phobos, it's a D runtime vestige. It's not 
getting inlined even in release builds with lto, whereas that 
manual version would. Also, benchmark with runtime strings, not 
literals, otherwise the compiler might even swallow the thing 
whole.


What you're benchmarking is, basically, inlined optimized search 
in a literal versus a function call.


Re: How to loop through characters of a string in D language?

2021-12-22 Thread Salih Dincer via Digitalmars-d-learn
On Monday, 13 December 2021 at 09:36:57 UTC, Ola Fosheim Grøstad 
wrote:

```d
@safe:

string prematureoptimizations(string s, char stripchar) 
@trusted {

import core.memory;
immutable uint flags = 
GC.BlkAttr.NO_SCAN|GC.BlkAttr.APPENDABLE;

char* begin = cast(char*)GC.malloc(s.length+1, flags);
char* end = begin + 1;
foreach(c; s) {
immutable size_t notsemicolon = c != stripchar;
// hack: avoid conditional by writing semicolon outside 
buffer

*(end - notsemicolon) = c;
end += notsemicolon;
}
immutable size_t len = end - begin - 1;
begin = cast(char*)GC.realloc(begin, len, flags);
return cast(string)begin[0..len];
}

void main() {
import std.stdio;
string str = "abc;def;ab";
writeln(prematureoptimizations(str, ';'));
}
```


It seems faster than algorithms in Phobos. We would love to see 
this in our new Phobos.


```d
enum str = "abc;def;gh";
enum res = "abcdefgh";

void main()
{
  void mallocReplace()
  {
import core.memory;

immutable uint flags =
  GC.BlkAttr.NO_SCAN|
  GC.BlkAttr.APPENDABLE;

char* begin = cast(char*)GC.malloc(str.length+1, flags);
char* end = begin + 1;

foreach(c; str)
{
  immutable size_t f = c != ';';
  *(end - f) = c;
  end += f;
}
immutable size_t len = end - begin - 1;
begin = cast(char*)GC.realloc(begin, len, flags);

assert(begin[0..len] == res);
  }

  void normalReplace()
  {
import std.string;

string result = str.replace(';',"");
assert(result == res);
  }

  void delegate() t1 = 
  void delegate() t2 = 

  import std.stdio : writefln;
  import std.datetime.stopwatch : benchmark;

  auto bm = benchmark!(t1, t2)(1_000_000);

  writefln("Replace: %s msecs", bm[0].total!"msecs");
  writefln("Malloc : %s msecs", bm[1].total!"msecs");
}/* Console Out:
Replace: 436 msecs
Malloc : 259 msecs
*/
```


Re: How to loop through characters of a string in D language?

2021-12-13 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Friday, 10 December 2021 at 18:47:53 UTC, Stanislav Blinov 
wrote:
Threshold could be relative for short strings and absolute for 
long ones. Makes little sense reallocating if you only waste a 
couple bytes, but makes perfect sense if you've just removed 
pages and pages of semicolons ;)


Like this?

```
@safe:

string prematureoptimizations(string s, char stripchar) @trusted {
import core.memory;
immutable uint flags = 
GC.BlkAttr.NO_SCAN|GC.BlkAttr.APPENDABLE;

char* begin = cast(char*)GC.malloc(s.length+1, flags);
char* end = begin + 1;
foreach(c; s) {
immutable size_t notsemicolon = c != stripchar;
// hack: avoid conditional by writing semicolon outside 
buffer

*(end - notsemicolon) = c;
end += notsemicolon;
}
immutable size_t len = end - begin - 1;
begin = cast(char*)GC.realloc(begin, len, flags);
return cast(string)begin[0..len];
}

void main() {
import std.stdio;
string str = "abc;def;ab";
writeln(prematureoptimizations(str, ';'));
}

```


Re: How to loop through characters of a string in D language?

2021-12-12 Thread bauss via Digitalmars-d-learn

On Monday, 13 December 2021 at 05:46:06 UTC, forkit wrote:
On Saturday, 11 December 2021 at 09:25:37 UTC, Ola Fosheim 
Grøstad wrote:


```putchar(…)``` is too slow!




On planet Mars maybe, but here on earth, my computer can do 
about 4 billion ticks per second, and my entire program (using 
putchar) takes only 3084 ticks.


Can I borrow a couple of your ticks?


Re: How to loop through characters of a string in D language?

2021-12-12 Thread forkit via Digitalmars-d-learn
On Saturday, 11 December 2021 at 09:25:37 UTC, Ola Fosheim 
Grøstad wrote:


```putchar(…)``` is too slow!




On planet Mars maybe, but here on earth, my computer can do about 
4 billion ticks per second, and my entire program (using putchar) 
takes only 3084 ticks.





Re: How to loop through characters of a string in D language?

2021-12-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
Of course, since it is easy to mess up and use ranges in the 
wrong way, you might want to add ```assert```s. That is most 
likely *helpful* to newbies that might want to use your kickass 
library function:


```
auto helpfuldeatheater(char stripchar)(string str) {
struct voldemort {
immutable(char)* begin, end;
bool empty(){ return begin == end; }
char front(){ assert(!empty); return *begin; }
char back()@trusted{ assert(!empty); return *(end-1); }
void popFront()@trusted{
assert(!empty);
		while(begin != end){begin++; if (*begin != stripchar) 
break; }

}
void popBack()@trusted{
assert(!empty);
while(begin != end){end--; if (*(end-1) != stripchar) 
break; }

}
this(string s)@trusted{
begin = s.ptr;
end = s.ptr + s.length;
while(begin!=end && *begin==stripchar) begin++;
while(begin!=end && *(end-1)==stripchar) end--;
}
}
return voldemort(str);
}
```



Re: How to loop through characters of a string in D language?

2021-12-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Sunday, 12 December 2021 at 08:58:29 UTC, Ola Fosheim Grøstad 
wrote:

this(string s)@trusted{
begin = s.ptr;
end = s.ptr + s.length;
}
}


Bug, it fails if the string ends or starts with ';'.

Fix:

```
this(string s)@trusted{
begin = s.ptr;
end = s.ptr + s.length;
while(begin!=end && *begin==stripchar) begin++;
while(begin!=end && *(end-1)==stripchar) end--;
}
```



Re: How to loop through characters of a string in D language?

2021-12-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Saturday, 11 December 2021 at 19:50:55 UTC, russhy wrote:
you need to import a 8k lines of code module that itself 
imports other modules, and then the code is hard to read


I agree.

```
@safe:

auto deatheater(char stripchar)(string str) {
struct voldemort {
immutable(char)* begin, end;
bool empty(){ return begin == end; }
char front(){ return *begin; }
char back()@trusted{ return *(end-1); }
void popFront()@trusted{
while(begin != end){begin++; if (*begin != stripchar) 
break; }

}
void popBack()@trusted{
while(begin != end){end--; if (*(end-1) != stripchar) 
break; }

}
this(string s)@trusted{
begin = s.ptr;
end = s.ptr + s.length;
}
}
return voldemort(str);
}


void main() {
import std.stdio;
string str = "abc;def;ab";
foreach(c; deatheater!';'(str)) write(c);
writeln();
foreach_reverse(c; deatheater!';'(str)) write(c);
}

```




Re: How to loop through characters of a string in D language?

2021-12-11 Thread russhy via Digitalmars-d-learn

On Saturday, 11 December 2021 at 18:51:12 UTC, Rumbu wrote:

On Saturday, 11 December 2021 at 14:42:53 UTC, russhy wrote:

Here is mine

- 0 allocations

- configurable

- let's you use it how you wish

- fast




You know that this is already in phobos?


```
"abc;def;ghi".splitter(';').joiner
```


you need to import a 8k lines of code module that itself imports 
other modules, and then the code is hard to read


https://github.com/dlang/phobos/blob/v2.098.0/std/algorithm/iteration.d#L2917


Re: How to loop through characters of a string in D language?

2021-12-11 Thread Rumbu via Digitalmars-d-learn

On Saturday, 11 December 2021 at 14:42:53 UTC, russhy wrote:

Here is mine

- 0 allocations

- configurable

- let's you use it how you wish

- fast




You know that this is already in phobos?


```
"abc;def;ghi".splitter(';').joiner
```



Re: How to loop through characters of a string in D language?

2021-12-11 Thread russhy via Digitalmars-d-learn

Here is mine

- 0 allocations

- configurable

- let's you use it how you wish

- fast


```D
import std;
void main()
{
string a = "abc;def;ab";
writeln("a => ", a);

foreach(item; split(a, ';'))
writeln("\t", item);


string b = "abc;def   ;ab";
writeln("a => ", b);

foreach(item; split(b, ';', SplitOption.TRIM))
writeln("\t", item);


string c= "abc;;   ;def   ;ab";
writeln("a => ",c);

foreach(item; split(c, ';', SplitOption.TRIM | 
SplitOption.REMOVE_EMPTY))

writeln("\t", item);
}

SplitIterator!T split(T)(const(T)[] buffer, const(T) delimiter, 
SplitOption option = SplitOption.NONE)

{
return SplitIterator!T(buffer, delimiter, option);
}

struct SplitIterator(T)
{
const(T)[] buffer;
const(T) delimiter;
SplitOption option;
int index = 0;

int count()
{
int c = 0;
foreach(line; this)
{
c++;
}
index = 0;
return c;
}

const(T) get(int index)
{
return buffer[index];
}

int opApply(scope int delegate(const(T)[]) dg)
{
auto length = buffer.length;
for (int i = 0; i < length; i++)
{
if (buffer[i] == '\0')
{
length = i;
break;
}
}

int result = 0;
for (int i = index; i < length; i++)
{
int entry(int start, int end)
{
// trim only if we got something
if ((end - start > 0) && (option & 
SplitOption.TRIM))

{
for (int j = start; j < end; j++)
if (buffer[j] == ' ')
start += 1;
else
break;
for (int k = end; k >= start; k--)
if (buffer[k - 1] == ' ')
end -= 1;
else
break;

// nothing left
if(start >= end) return 0;
}

//printf("%i to %i :: %i :: total: %lu\n", start, end, index, 
buffer.length);

return dg(buffer[start .. end]) != 0;
}

auto c = buffer[i];
if (c == delimiter)
{
if (i == index && (option & 
SplitOption.REMOVE_EMPTY))

{
// skip if we keep finding the delimiter
index = i + 1;
continue;
}

if ((result = entry(index, i)) != 0)
break;

// skip delimiter for next result
index = i + 1;
}

// handle what's left
if ((i + 1) == length)
{
result = entry(index, i + 1);
}
}
return result;
}

// copy from above, only replace if above has changed
int opApply(scope int delegate(int, const(T)[]) dg)
{
auto length = buffer.length;
for (int i = 0; i < length; i++)
{
if (buffer[i] == '\0')
{
length = i;
break;
}
}

int n = 0;
int result = 0;
for (int i = index; i < length; i++)
{
int entry(int start, int end)
{
// trim only if we got something
if ((end - start > 0) && (option & 
SplitOption.TRIM))

{
for (int j = start; j < end; j++)
if (buffer[j] == ' ')
start += 1;
else
break;
for (int k = end; k >= start; k--)
if (buffer[k - 1] == ' ')
end -= 1;
else
break;

// nothing left
if(start >= end) return 0;
}

//printf("%i to %i :: %i :: total: %lu\n", start, end, index, 
buffer.length);

return dg(n++, buffer[start .. end]) != 0;
}

auto c = buffer[i];
if (c == delimiter)
{
if (i == index && (option & 
SplitOption.REMOVE_EMPTY))

{
// skip if we keep finding the delimiter
index = i + 1;
continue;
}

if ((result = entry(index, i)) != 0)
break;

// skip delimiter for next result
index = i + 1;

Re: How to loop through characters of a string in D language?

2021-12-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Saturday, 11 December 2021 at 09:40:47 UTC, Stanislav Blinov 
wrote:
On Saturday, 11 December 2021 at 09:34:17 UTC, Ola Fosheim 
Grøstad wrote:



void donttrythisathome(string s, char stripchar) @trusted {
import core.stdc.stdlib;
char* begin = cast(char*)alloca(s.length);


A function with that name, and calling alloca to boot, cannot 
be @trusted ;)


:-)

But I am very trustworthy person! PROMISE!!!



Re: How to loop through characters of a string in D language?

2021-12-11 Thread Stanislav Blinov via Digitalmars-d-learn
On Saturday, 11 December 2021 at 09:34:17 UTC, Ola Fosheim 
Grøstad wrote:



void donttrythisathome(string s, char stripchar) @trusted {
import core.stdc.stdlib;
char* begin = cast(char*)alloca(s.length);


A function with that name, and calling alloca to boot, cannot be 
@trusted ;)


Re: How to loop through characters of a string in D language?

2021-12-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Saturday, 11 December 2021 at 09:34:17 UTC, Ola Fosheim 
Grøstad wrote:

@system


Shouldn't be there. Residual leftovers… (I don't want to confuse 
newbies!)




Re: How to loop through characters of a string in D language?

2021-12-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Saturday, 11 December 2021 at 08:46:32 UTC, forkit wrote:
On Saturday, 11 December 2021 at 08:05:01 UTC, Ola Fosheim 
Grøstad wrote:


Using libraries can trigger hidden allocations.


ok. fine. no unnecessary, hidden allocations then.

// --

module test;

import core.stdc.stdio : putchar;

nothrow @nogc void main()
{
string str = "abc;def;ab";

ulong len = str.length;

for (ulong i = 0; i < len; i++)
{
if (cast(int) str[i] != ';')
putchar(cast(int) str[i]);
}
}

// --


```putchar(…)``` is too slow!


```

@safe:

extern (C) long write(long, const void *, long);


void donttrythisathome(string s, char stripchar) @trusted {
import core.stdc.stdlib;
char* begin = cast(char*)alloca(s.length);
char* end = begin;
foreach(c; s) if (c != stripchar) *(end++) = c;
write(0, begin, end - begin);
}


@system
void main() {
string str = "abc;def;ab";
donttrythisathome(str, ';');
}




Re: How to loop through characters of a string in D language?

2021-12-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Saturday, 11 December 2021 at 09:26:06 UTC, Stanislav Blinov 
wrote:
What you're showing is... indeed, don't do this, but I fail to 
see what that has to do with my suggestion, or the original 
code.


You worry too much, just have fun with differing ways of 
expressing the same thing.


(Recursion can be completely fine if the compiler supports it 
well. Tail recursion that is, not my example.)


Again, that is a different algorithm than what I was responding 
to.


Slightly different, but same idea. Isn't the point of this thread 
to present N different ways of doing the same thing? :-)






Re: How to loop through characters of a string in D language?

2021-12-11 Thread Stanislav Blinov via Digitalmars-d-learn
On Friday, 10 December 2021 at 23:53:47 UTC, Ola Fosheim Grøstad 
wrote:



```d
char[] dontdothis(string s, int i=0, int skip=0){
if (s.length == i) return new char[](i - skip);
if (s[i] == ';') return dontdothis(s, i+1, skip+1);
auto r = dontdothis(s, i+1, skip);
r[i-skip] = s[i];
return r;
}
```


That is about 500% not what I meant. At all. Original code in 
question:


- duplicates string unconditionally as mutable storage
- uses said mutable storage to gather all non-semicolons
- duplicates said mutable storage (again) as immutable

I suggested to make the second duplicate conditional, based on 
amount of space freed by skipping semicolons.


What you're showing is... indeed, don't do this, but I fail to 
see what that has to do with my suggestion, or the original code.


Scanning short strings twice is not all that expensive as they 
will stay in the CPU cache > when you run over them a second 
time.



```d
import std.stdio;

@safe:
string stripsemicolons(string s) @trusted {
int i,n;
foreach(c; s) n += c != ';'; // premature optimization
auto r = new char[](n);
foreach(c; s) if (c != ';') r[i++] = c;
return cast(string)r;
}
```


Again, that is a different algorithm than what I was responding 
to. But sure, short strings - might as well. So long as you do 
track the distinction somewhere up in the code and don't simply 
call this on all strings.


Re: How to loop through characters of a string in D language?

2021-12-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Saturday, 11 December 2021 at 08:46:32 UTC, forkit wrote:
On Saturday, 11 December 2021 at 08:05:01 UTC, Ola Fosheim 
Grøstad wrote:


Using libraries can trigger hidden allocations.


ok. fine. no unnecessary, hidden allocations then.

// --

module test;

import core.stdc.stdio : putchar;

nothrow @nogc void main()
{
string str = "abc;def;ab";

ulong len = str.length;

for (ulong i = 0; i < len; i++)
{
if (cast(int) str[i] != ';')
putchar(cast(int) str[i]);
}
}

// --


```putchar(…)``` is too slow!


```

@safe:

extern (C) long write(long, const void *, long);


void donttrythisathome(string s, char stripchar) @trusted {
import core.stdc.stdlib;
char* begin = cast(char*)alloca(s.length);
char* end = begin;
foreach(c; s) if (c != stripchar) *(end++) = c;
write(0, begin, end - begin);
}


@system
void main() {
string str = "abc;def;ab";
donttrythisathome(str, ';');
}




Re: How to loop through characters of a string in D language?

2021-12-11 Thread forkit via Digitalmars-d-learn
On Saturday, 11 December 2021 at 08:05:01 UTC, Ola Fosheim 
Grøstad wrote:


Using libraries can trigger hidden allocations.


ok. fine. no unnecessary, hidden allocations then.

// --

module test;

import core.stdc.stdio : putchar;

nothrow @nogc void main()
{
string str = "abc;def;ab";

ulong len = str.length;

for (ulong i = 0; i < len; i++)
{
if (cast(int) str[i] != ';')
putchar(cast(int) str[i]);
}
}

// --



Re: How to loop through characters of a string in D language?

2021-12-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Friday, 10 December 2021 at 18:47:53 UTC, Stanislav Blinov 
wrote:
Threshold could be relative for short strings and absolute for 
long ones. Makes little sense reallocating if you only waste a 
couple bytes, but makes perfect sense if you've just removed 
pages and pages of semicolons ;)


Scanning short strings twice is not all that expensive as they 
will stay in the CPU cache when you run over them a second time.


```
import std.stdio;

@safe:

string stripsemicolons(string s) @trusted {
int i,n;
foreach(c; s) n += c != ';'; // premature optimization
auto r = new char[](n);
foreach(c; s) if (c != ';') r[i++] = c;
return cast(string)r;
}

int main() {
writeln(stripsemicolons("abc;def;ab"));
return 0;
}
```



Re: How to loop through characters of a string in D language?

2021-12-11 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Saturday, 11 December 2021 at 00:39:15 UTC, forkit wrote:

On Friday, 10 December 2021 at 22:35:58 UTC, Arjan wrote:


"abc;def;ghi".tr(";", "", "d" );



I don't think we have enough ways of doing the same thing yet...

so here's one more..

"abc;def;ghi".substitute(";", "");


Using libraries can trigger hidden allocations.

```
import std.stdio;

string garbagefountain(string s){
if (s.length == 1) return s == ";" ? "" : s;
return garbagefountain(s[0..$/2]) ~ 
garbagefountain(s[$/2..$]);

}

int main() {
writeln(garbagefountain("abc;def;ab"));
return 0;
}

```



Re: How to loop through characters of a string in D language?

2021-12-10 Thread forkit via Digitalmars-d-learn

On Friday, 10 December 2021 at 22:35:58 UTC, Arjan wrote:


"abc;def;ghi".tr(";", "", "d" );



I don't think we have enough ways of doing the same thing yet...

so here's one more..

"abc;def;ghi".substitute(";", "");



Re: How to loop through characters of a string in D language?

2021-12-10 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Friday, 10 December 2021 at 18:47:53 UTC, Stanislav Blinov 
wrote:
Oooh, finally someone suggested to preallocate storage for all 
these reinventions of the wheel :D


```
import std.stdio;

char[] dontdothis(string s, int i=0, int skip=0){
if (s.length == i) return new char[](i - skip);
if (s[i] == ';') return dontdothis(s, i+1, skip+1);
auto r = dontdothis(s, i+1, skip);
r[i-skip] = s[i];
return r;
}

int main() {
string s = "abc;def;ab";
string s_new = cast(string)dontdothis(s);
writeln(s_new);
return 0;
}
```



Re: How to loop through characters of a string in D language?

2021-12-10 Thread Arjan via Digitalmars-d-learn

On Friday, 10 December 2021 at 06:24:27 UTC, Rumbu wrote:

On Wednesday, 8 December 2021 at 11:23:45 UTC, BoQsc wrote:

Let's say I want to skip characters and build a new string.
The character I want to skip: `;`

Expected result:
```
abcdefab
```


Since it seems there is a contest here:

```d
"abc;def;ghi".split(';').join();
```

:)

```d
"abc;def;ghi".tr(";", "", "d" );
```



Re: How to loop through characters of a string in D language?

2021-12-10 Thread forkit via Digitalmars-d-learn

On Friday, 10 December 2021 at 12:15:18 UTC, Rumbu wrote:


I thought it's a beauty contest.



Well, if it's a beauty contest, then i got a beauty..

char[("abc;def;ab".length - count("abc;def;ab", ";"))] b = 
"abc;def;ab".replace(";", "");




Re: How to loop through characters of a string in D language?

2021-12-10 Thread Luís Ferreira via Digitalmars-d-learn
Yes it will. You can use lazy templates instead, like splitter and joiner, 
which splits and joins lazily, respectively. LDC can optimize those templates 
fairly well and avoid too much lazy calls and pretty much constructs the logic 
equivalent to for loop.

On 10 December 2021 11:06:21 WET, IGotD- via Digitalmars-d-learn 
 wrote:
>On Friday, 10 December 2021 at 06:24:27 UTC, Rumbu wrote:
>
>> 
>> Since it seems there is a contest here:
>> 
>> ```d
>> "abc;def;ghi".split(';').join();
>> ```
>> 
>> :)
>
>Would that become two for loops or not?


  1   2   3   4   5   6   >