forgetting -betterC means no runtime bounds checking?

2023-01-05 Thread areYouSureAboutThat via Digitalmars-d-learn
I was playing around with betterC, when I discovered, that if i 
accidently forget to provide -betterC to the compiler, it will 
still compile this, but, there will be no runtime bounds checking 
occuring.


My question is: why is there no bounds checking occurring if I 
forget to use -betterC?


module test;

extern(C) void main()
{
import core.stdc.stdio : printf;


int[5] arr = [ 0, 1, 2, 3, 4];

for (int i = 0; i < 10; i++) // oops!
{
printf("%d\n", arr[i]);
}
}



Re: forgetting -betterC means no runtime bounds checking?

2023-01-05 Thread areYouSureAboutThat via Digitalmars-d-learn
On Thursday, 5 January 2023 at 09:10:00 UTC, areYouSureAboutThat 
wrote:




btw. the output (when you forget to use -betterC):

0
1
2
3
4
src/rt/dwarfeh.d:330: uncaught exception reached top of stack
This might happen if you're missing a top level catch in your 
fiber or signal handler
core.exception.ArrayIndexError@test.d(25): index [5] exceeds 
array of length 5

Aborted (core dumped)





Re: forgetting -betterC means no runtime bounds checking?

2023-01-05 Thread Richard (Rikki) Andrew Cattermole via Digitalmars-d-learn

On 05/01/2023 10:17 PM, areYouSureAboutThat wrote:

src/rt/dwarfeh.d:330: uncaught exception reached top of stack
This might happen if you're missing a top level catch in your fiber or 
signal handler
core.exception.ArrayIndexError@test.d(25): index [5] exceeds array of 
length 5

Aborted (core dumped)


Looks like an exception to me, which is what the default for bounds 
check on error will do.


Because you are not using the druntime entry point, its not being caught 
and made to look nice to you.


Re: forgetting -betterC means no runtime bounds checking?

2023-01-05 Thread Mathias LANG via Digitalmars-d-learn
On Thursday, 5 January 2023 at 09:17:28 UTC, areYouSureAboutThat 
wrote:
core.exception.ArrayIndexError@test.d(25): index [5] exceeds 
array of length 5

Aborted (core dumped)


This is bounds checking happening.


Re: forgetting -betterC means no runtime bounds checking?

2023-01-05 Thread Tejas via Digitalmars-d-learn
On Thursday, 5 January 2023 at 09:10:00 UTC, areYouSureAboutThat 
wrote:
I was playing around with betterC, when I discovered, that if i 
accidently forget to provide -betterC to the compiler, it will 
still compile this, but, there will be no runtime bounds 
checking occuring.


My question is: why is there no bounds checking occurring if I 
forget to use -betterC?


module test;

extern(C) void main()
{
import core.stdc.stdio : printf;


int[5] arr = [ 0, 1, 2, 3, 4];

for (int i = 0; i < 10; i++) // oops!
{
printf("%d\n", arr[i]);
}
}


Works on run.dlang.io for me:
```sh
0
1
2
3
4
dmd_runJFfSJW: onlineapp.d:12: Assertion 'array index out of 
bounds' failed.

Error: program killed by signal 6
```

On my personal ldc 1.27.1:
```sh
(base) [tejasgarhewal@fedora ~]$ ldc2 -betterC -run ./D/oob.d
0
1
2
3
4
oob-06265c: ./D/oob.d:9: Assertion 'array overflow' failed.
Error: /tmp/oob-06265c failed with status: -2
   message: Aborted (core dumped)
Error: program received signal 2 (Interrupt)
(base) [tejasgarhewal@fedora ~]$
```


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: 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?




Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Vijay Nayar via Digitalmars-d-learn
I've run into an unexpected problem that only seems to happen in 
unittests, but not outside of them. Consider the following 
example:


```
unittest {
  class Ab {
int a;
string b;

static class Builder {
  int _a;
  string _b;
  Builder a(int a) {
_a = a;
return this;
  }
  Builder b(string b) {
_b = b;
return this;
  }
  Ab build() {
Ab t = new Ab();
t.a = _a;
t.b = _b;
return t;
  }
}
  }

  Ab ab = new Ab.Builder()
  .a(1)
  .b("ham")
  .build();
  assert(ab.a == 1);
  assert(ab.b == "ham");
}
```

This fails to compile with the following error:
```
Generating test runner configuration 'builder-test-library' for 
'library' (library).
Starting Performing "unittest" build using /usr/bin/dmd for 
x86_64.
Building builder ~master: building configuration 
[builder-test-library]
source/builder.d(58,16): Error: outer function context of 
`builder.__unittest_L41_C1` is needed to `new` nested class 
`builder.__unittest_L41_C1.Ab`

Error /usr/bin/dmd failed with exit code 1.
```

However, if I move the class definition outside of the unittest 
block, then everything works fine:

```
class Ab {
  int a;
  string b;

  static class Builder {
int _a;
string _b;
Builder a(int a) {
  _a = a;
  return this;
}
Builder b(string b) {
  _b = b;
  return this;
}
Ab build() {
  Ab t = new Ab();
  t.a = _a;
  t.b = _b;
  return t;
}
  }
}

unittest {
  Ab ab = new Ab.Builder()
  .a(1)
  .b("ham")
  .build();
  assert(ab.a == 1);
  assert(ab.b == "ham");
}
```

```
 Generating test runner configuration 
'builder-test-library' for 'library' (library).
Starting Performing "unittest" build using /usr/bin/dmd for 
x86_64.
Building builder ~master: building configuration 
[builder-test-library]

 Linking builder-test-library
 Running builder-test-library
2 modules passed unittests
```

Why is this error only found when declaring a class in the 
unittest?


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: Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote:
Why is this error only found when declaring a class in the 
unittest?


A unittest is just a special function, it can run code and have 
local variables.


classes and structs declared inside it have access to those local 
contexts, which it calls the outer function context.


Make the outer class `static` too to lift it out of this and your 
error should go away.


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: forgetting -betterC means no runtime bounds checking?

2023-01-05 Thread tsbockman via Digitalmars-d-learn
On Thursday, 5 January 2023 at 09:10:00 UTC, areYouSureAboutThat 
wrote:
My question is: why is there no bounds checking occurring if I 
forget to use -betterC?


module test;

extern(C) void main()


Note that whether bounds checking is performed depends on 
[compiler 
switches](https://dlang.org/dmd-windows.html#switch-boundscheck), 
and that there is a mode where `@safe` functions are checked, but 
`@system` functions (which your `main` appears to be) are not. 
This mode is the default for `-release` builds:

```
-boundscheck=[on|safeonly|off ]
Controls if bounds checking is enabled.
on: Bounds checks are enabled for all code. This is the 
default.


safeonly: Bounds checks are enabled only in @safe code. This 
is the default for -release builds.


off: Bounds checks are disabled completely (even in @safe 
code). This option should be used with caution and as a last 
resort to improve performance. Confirm turning off @safe bounds 
checks is worthwhile by benchmarking.

```
So, if you want bounds checking, make  sure you either have 
`-boundscheck=on`, or use an `@safe` function together with 
`-boundscheck=safeonly`.


Re: Is there a way to enforce UFCS?

2023-01-05 Thread Dom DiSc via Digitalmars-d-learn

On Wednesday, 4 January 2023 at 14:21:46 UTC, bauss wrote:

```d
class Foo {
  int bar;

  void setBar(Foo foo, int value) {
foo.bar = value;
  }
}

void main() {
  foo.setBar(100); // Not UFCS - just method call to the class
  foo.setBar = 100; // Not UFCS - simply a setter function call 
(equal to the above)

  setBar(foo, 100); // Error
}
```


I think this is really another usecase for @property: we should 
forbid the function call syntax for them (so one needs to use 
them like a variable).
This is useful to enable library authors to enforce this, so that 
if a property is replaced by a variable (e.g. during 
refactoring), it's not a braking change for the users of the 
library.
Else it could be that setters or getters are directly called, 
which would not compile anymore with a variable (that doesn't 
have getters or setters).


@properties are intended to be used like variables - the only 
differences (and the reason why they exist) is the read or write 
protection they provide, and that they may be calculated on the 
fly (not stored in memory at all). That they are realized with a 
construct that looks similar to (a pair of) functions should be 
completely transparent for the user of a library.


Properties are not functions. If you want a function, use a 
function. If @properties would be the same as functions, they are 
superfluous garbage. Either make something useful out of them or 
remove them.




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: Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Vijay Nayar via Digitalmars-d-learn

On Thursday, 5 January 2023 at 13:47:24 UTC, Adam D Ruppe wrote:

On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote:
Why is this error only found when declaring a class in the 
unittest?


A unittest is just a special function, it can run code and have 
local variables.


classes and structs declared inside it have access to those 
local contexts, which it calls the outer function context.


Make the outer class `static` too to lift it out of this and 
your error should go away.


That's very informative, I didn't realize that `unittest` is 
actually a function.


It raises another question one step deeper, what does it mean to 
define a non-static class within a function? Does that class 
inherit the scope of the function it is inside, similar to how an 
inner class does with an outer class?


Re: Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 5 January 2023 at 16:38:49 UTC, Vijay Nayar wrote:
Does that class inherit the scope of the function it is inside, 
similar to how an inner class does with an outer class?


yup. They can see the local variables from the function.




Re: Error "Outer Function Context is Needed" when class declared in unittest

2023-01-05 Thread Vijay Nayar via Digitalmars-d-learn

On Thursday, 5 January 2023 at 16:41:32 UTC, Adam D Ruppe wrote:

On Thursday, 5 January 2023 at 16:38:49 UTC, Vijay Nayar wrote:
Does that class inherit the scope of the function it is 
inside, similar to how an inner class does with an outer class?


yup. They can see the local variables from the function.


Glad to learn that. Having worked many years in the Java world, 
where basically "class" and "scope" are nearly synonymous, I just 
assumed that classes could only get the scope of other classes, 
it never occurred to me that it could get a scope from a function.


Thanks for the explanation!


Re: Address of a class object

2023-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 05, 2023 at 06:32:47AM +, areYouSureAboutThat via 
Digitalmars-d-learn wrote:
[...]
> Second, to be sure your getting the correct results, it would be nice
> if there was a 'category of type' in std.traits for:
> 
> isAllocatedOnStack
> isAllocatedOnHeap
> 
> As it is, your just guessing (although the addresses printed will
> clear this up for you anyway I guess).

In general, it's not possible to determine whether an arbitrary
reference is pointing to the stack or the heap, because it could have
come from anywhere.  You can only determine this if you are privy to the
internal implementation details of the allocator or code that created
the reference (GC, other allocator, or whatever took an address of a
stack-allocated object), or the platform-specific details of your
runtime environment (range of stack addresses).


> Also, I cannot read hex,
[...]

IMNSHO, anyone who claims to be a programmer should at least know that
much.  As Knuth once said,

People who are more than casually interested in computers should
have at least some idea of what the underlying hardware is like.
Otherwise the programs they write will be pretty weird.
-- D. Knuth


T

-- 
"Real programmers can write assembly code in any language. :-)" -- Larry Wall


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: Is there a way to enforce UFCS?

2023-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 05, 2023 at 02:32:17PM +, Dom DiSc via Digitalmars-d-learn 
wrote:
[...]
> I think this is really another usecase for @property: we should forbid the
> function call syntax for them (so one needs to use them like a variable).
[...]
> Properties are not functions. If you want a function, use a function. If
> @properties would be the same as functions, they are superfluous garbage.
> Either make something useful out of them or remove them.

We have been talking about deprecating and removing @property for years
now.  Somebody just has to bite the bullet and push it through the
deprecation process...

... OR come up with a DIP that implements @property in a sane, fully
worked out way, not the half-hearted, incomplete, leaky implementation
that it is today.

//

In my own code, I've stopped bothering with @property for the most part.
Parentheses are optional for argumentless functions in general anyway,
so there's really no need to write @property on anything. This works:

struct S {
private int _x;
int x() { return _x; }
}

S s;
int y = s.x;

The only significant thing @property does right now is to add confusion
when the unary & operator is used or when the property function returns
a delegate.  Not worth the trouble, I say.  Just don't use @property at
all, plain old member functions work just fine.


T

-- 
Some ideas are so stupid that only intellectuals could believe them. -- George 
Orwell


Re: Address of a class object

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

On Thursday, 5 January 2023 at 05:59:26 UTC, Ali Çehreli wrote:

While we're here, you can force the class objects to be on the 
stack as well:


scope MyClassVar1 = new MyClass();

I replaced 'auto' with 'scope'.

Ali


Very interesting.  Thanks Ali.




GC interaction with malloc/free

2023-01-05 Thread DLearner via Digitalmars-d-learn
Suppose there is a D main program (not marked anywhere with 
@nogc), that _both_


A: Calls one or more C functions that themselves call 
malloc/free; and also
B: Calls one or more D functions that themselves call malloc/free 
via `import core.stdc.stdlib;`


Assuming the malloc/free's are used correctly, does this 
situation risk crashing the D main program?


Best regards


Re: GC interaction with malloc/free

2023-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 05, 2023 at 07:49:38PM +, DLearner via Digitalmars-d-learn 
wrote:
> Suppose there is a D main program (not marked anywhere with @nogc),
> that _both_
> 
> A: Calls one or more C functions that themselves call malloc/free; and
> also
> B: Calls one or more D functions that themselves call malloc/free via
> `import core.stdc.stdlib;`
> 
> Assuming the malloc/free's are used correctly, does this situation
> risk crashing the D main program?
[...]

core.stdc.stdlib.{malloc,free} *is* the exact same malloc/free that C
uses, it has nothing to do with the GC.  The allocated memory is taken
from the malloc/free part of the heap, which is disjoint from the heap
memory managed by the GC.

So, it should not cause any crashes.


T

-- 
Маленькие детки - маленькие бедки.


Re: GC interaction with malloc/free

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

On Thursday, 5 January 2023 at 19:54:01 UTC, H. S. Teoh wrote:
On Thu, Jan 05, 2023 at 07:49:38PM +, DLearner via 
Digitalmars-d-learn wrote:
Suppose there is a D main program (not marked anywhere with 
@nogc),

that _both_

A: Calls one or more C functions that themselves call 
malloc/free; and

also
B: Calls one or more D functions that themselves call 
malloc/free via

`import core.stdc.stdlib;`

Assuming the malloc/free's are used correctly, does this 
situation risk crashing the D main program?

[...]

core.stdc.stdlib.{malloc,free} *is* the exact same malloc/free 
that C uses, it has nothing to do with the GC.  The allocated 
memory is taken from the malloc/free part of the heap, which is 
disjoint from the heap memory managed by the GC.


So, it should not cause any crashes.


T


That's comforting, but there is a reference in:

https://dlang.org/blog/2017/09/25/go-your-own-way-part-two-the-heap/

'...Given that it’s rarely recommended to disable the GC 
entirely, most D programs allocating outside the GC heap will 
likely also be using memory from the GC heap in the same program. 
In order for the GC to properly do its job, it needs to be 
informed of any non-GC memory that contains, or may potentially 
contain, references to memory from the GC heap.'


Followed by things that have to be done (GC.addRange) to avoid 
interaction effects?


Re: GC interaction with malloc/free

2023-01-05 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 05, 2023 at 08:18:42PM +, DLearner via Digitalmars-d-learn 
wrote:
> On Thursday, 5 January 2023 at 19:54:01 UTC, H. S. Teoh wrote:
[...]
> > core.stdc.stdlib.{malloc,free} *is* the exact same malloc/free that
> > C uses, it has nothing to do with the GC.  The allocated memory is
> > taken from the malloc/free part of the heap, which is disjoint from
> > the heap memory managed by the GC.
> > 
> > So, it should not cause any crashes.
[...]
> That's comforting, but there is a reference in:
> 
> https://dlang.org/blog/2017/09/25/go-your-own-way-part-two-the-heap/
> 
> '...Given that it’s rarely recommended to disable the GC entirely,
> most D programs allocating outside the GC heap will likely also be
> using memory from the GC heap in the same program. In order for the GC
> to properly do its job, it needs to be informed of any non-GC memory
> that contains, or may potentially contain, references to memory from
> the GC heap.'
> 
> Followed by things that have to be done (GC.addRange) to avoid
> interaction effects?

You only need to do this if you will be storing pointers to GC-allocated
objects inside malloc-allocated objects.  E.g., if you malloc a struct
that contains a reference to a GC-allocated class object.

The reason for this precaution is because the GC needs to know all the
root pointers that eventually may point to a prospective object to be
garbage-collected.  If there are pointers to an object outside of the
areas the GC is aware of, e.g., in the malloc heap, then the GC may not
be able to correctly determine that there's still a reference to the
object, and may collect it prematurely, leading to a crash when you next
try to dereference the pointer to the object.

If there are no references from the malloc heap to the GC heap, then you
do not need to use GC.addRange.


T

-- 
Build a man a fire, and he is warm for a night. Set a man on fire, and he is 
warm for the rest of his life.


Re: Address of a class object

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

On Thursday, 5 January 2023 at 17:23:39 UTC, H. S. Teoh wrote:

On Thu, Jan 05, 2023 at 06:32:47AM +, areYouSureAboutThat

Also, I cannot read hex,

[...]

IMNSHO, anyone who claims to be a programmer should at least 
know that much.


??

Well, like all, I learnt this at uni. .. as well as lot of other 
useless stuff.


But in all my years as a well paid and productive 'programmer' 
;-) .. I cannot recall ever, a consistent need to read hex (using 
by brain, that is).


As such, those neuron connections needed to read hex do not exist 
anymore.


Even the neurons in my brain are smarted than Knuth.




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 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

```

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: Is there a way to enforce UFCS?

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

them or remove them.


I agree, forbidding function call syntax would be a great usecase 
for `@property`.


It will probably never get implemented though.


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 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.