Re: __gshared is "somewhat" transitive, isn't it ?

2024-05-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On Thursday, 16 May 2024 at 17:04:09 UTC, user1234 wrote:

Given

```d
struct S
{
int member;
}

__gshared S s;
```

It's clear that `s.member` is `__gshared` too, right ?
What does happen for

```d
struct S
{
int member;
static int globalMember;
}

__gshared S s;
```

Is then `S.globalMember` a TLS variable ? (I'd expect that)


`__gshared` is a storage class. It means, store this thing in the 
global memory segment. `static` storage class means store this 
thing in TLS.


Storage classes are *not* transitive, and they are not type 
constructors. They optionally might apply a type constructor to 
the type (such as the `const` storage class), but not always.


So in this case `typeof(s)` is `S`, not `__gshared S`. `s.member` 
is in the global segment since structs members are placed within 
the struct memory location (in this case, the global memory 
segment).


`globalMember` is placed in TLS because it's storage class is 
`static`, and `static` means, do not store with the instance 
(which for `s` would mean the global memory segment), but rather 
in TLS.


-Steve


Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?

2024-05-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 10 May 2024 at 11:05:28 UTC, Dukc wrote:



This also gets inferred as `pure` - meaning that if you use it 
twice for the same `WeakRef`, the compiler may reuse the result 
of the first dereference for the second call, without checking 
whether the referred value has changed!


This would be weak pure since the reference is mutable. This 
cannot be memoized.


-Steve


Re: "in" operator gives a pointer result from a test against an Associative Array?

2024-05-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 10 May 2024 at 01:00:09 UTC, Andy Valencia wrote:

On Friday, 10 May 2024 at 00:40:01 UTC, Meta wrote:
Yes. The reason for this is that it avoids having to 
essentially do the same check twice. If `in` returned a bool 
instead of a pointer, after checking for whether the element 
exists (which requires searching for the element in the 
associative array), you'd then have to actually *get* it from 
the array, which would require searching again. Returning a 
pointer to the element if it exists (or `null` if it doesn't) 
cuts this down to 1 operation.


Looking at Programming in D section 28.5, I'm guessing that 
pointer versus null is treated as the appropriate boolean value 
when consumed by an "if" test.  So that example is getting a 
pointer to a string, or null, but the example looks exactly as 
the same as if it had directly gotten a bool.


Yes, we say that a type has "truthiness" if it can be used in a 
condition (`while`, `if`, `assert`, etc).


For a pointer, `null` is considered "false", whereas any other 
value is considered "true". So you can use statements like 
`if(key in aa)` to test for membership. A very nice idiom is to 
check if a key is in an associative array, and if so, use the 
value that it maps to:


```d
if(auto v = key in aa) {
   // use *v as the value here
}
```

You can change your code to `return (e in this.members) !is null;`

-Steve


Re: TIL: statically initializing an Associative Array

2024-05-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On Tuesday, 7 May 2024 at 00:10:27 UTC, Andy Valencia wrote:
I had a set of default error messages to go with error code 
numbers, and did something along the lines of:


string[uint] error_text = [
400: "A message",
401: "A different message"
];

and got "expression  is not a constant"

I eventually found this discussion:
https://issues.dlang.org/show_bug.cgi?id=6238

I understand that it's problematic, but a message which makes 
it clearer that compile-time initialization of global AA's are 
not supported?  Because it cost me about a half hour trying to 
figure out what I was doing wrong.


This error message was changed in 2.101.x (unsure which point 
release):


```
onlineapp.d(1): Error: static initializations of associative 
arrays is not allowed.
onlineapp.d(1):associative arrays must be initialized at 
runtime: 
https://dlang.org/spec/hash-map.html#runtime_initialization

```



(My workaround was to initialize the data structure once during 
app startup.)


This was fixed [in 
2.106.0](https://dlang.org/changelog/2.106.0.html#dmd.static-assoc-array)


 please upgrade your compiler.

-Steve


Re: How can I put the current value of a variable into a delegate?

2024-05-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote:
Delegates can be a pain, as they often have results different 
from what one would intuitively expect. This can easily result 
in bugs.


Here's a line that caused a bug that took me awhile to find:
```
foreach(card; unitCards) card.submitted = delegate() => 
selectUnit(card.unit);

```

Each `UnitInfoCard` object (which `card` is a member of) 
contains a `Unit` object called `unit`. The intention of this 
line was that each object in `unitCards` would call 
`selectUnit` with it's own `unit` every time it calls 
`submitted`. Instead, every card calls `submitted` with the 
*last* value of `card`.


Yes, this is because the foreach loop reuses the same memory slot 
for `card`.


Even though this is allocated as a closure, it still only 
allocates the frame stack of the *enclosing function*, and does 
not allocate a new slot for each loop iteration.


You can force this by using a lambda which allocates the closure:

```d
foreach(card; unitCards)
card.submitted = (c2) { return () => selectUnit(c2.unit); 
}(card);

```

This is a lambda which accepts `card` as a parameter, and returns 
an appropriate delegate. It is important to use a parameter, 
because if you just use card inside there, it's still using the 
single stack frame of the calling function!


I renamed the inner parameter `c2` to avoid confusion, but you 
could name it `card` also. Essentially, the stack frame of the 
inner function is now allocated a closure, and it has it's own 
reference to `card` as a parameter.


This is a very old issue: 
https://issues.dlang.org/show_bug.cgi?id=2043 since "moved" to 
https://issues.dlang.org/show_bug.cgi?id=23136


I would love to see a solution, but the workaround at least 
exists!


-Steve


Re: Show dialog box for uncaught exception (Windows, lld-link)

2024-05-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 5 May 2024 at 14:55:20 UTC, SimonN wrote:
My application is a graphical game. I close stdout and stderr 
by passing `-subsystem:windows` to `lld-link` to suppress the 
extra console window. For a few fatal errors (missing required 
resources, can't open display, ...), I throw exceptions, log 
them to logfile, then re-throw them to crash. I can tell 
Windows users to look in the logfile, but it would be more 
fitting on Windows to show an error dialog box in addition to 
the logging.


```d
int realMain(string[] args)
{
   // all your normal code goes here
}

int main(string[] args)
{
version(Windows) {
try {
realMain(args);
} catch(Exception e) {
visualDisplayOfException(e);
throw e;
}
} else {
// presumably, non-windows systems shouldn't show a 
graphical Exception

// trace?
realMain(args);
}
}
```

-Steve


Re: Phobos function to remove all occurances from dynamic array?

2024-05-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On Wednesday, 1 May 2024 at 01:09:33 UTC, Liam McGillivray wrote:
This is presumably such a common task that I'm surprised it 
isn't easy to find the answer by searching;


Is there a standard library function that removes all elements 
from a dynamic array that matches an input argument?


In `std.array` there's the `replace` function which is supposed 
to replace all occurrences that match an input with another. It 
seems to work as described on strings, but I get compiler 
errors when using it on other array types. I've tried using it 
to replace occurrences of a certain object in an array with 
`[]` in order to remove all occurrences, but it's not allowed.


Is there a Phobos function that does what I want? It would be 
crazy if there isn't.


`remove`

https://dlang.org/phobos/std_algorithm_mutation.html#remove

```d
arr = arr.remove!(v => shouldBeRemoved(v));
```

Why the reassignment? Because `remove` removes elements *in 
place*, and does not change the range extents. It returns the 
portion of the range that contains the unremoved elements.


So to give an example:

```d
auto arr = [1, 2, 3, 4, 5];
auto result = arr.remove!(i => i % 2 == 1); // remove odd elements
assert(result == [2, 4]);

// first 2 are the slice that is stored in result
// the last three are leftovers.
assert(arr == [2, 4, 3, 4, 5]);
```

-Steve


Re: Adapting foreign iterators to D ranges

2024-04-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 22 April 2024 at 11:36:43 UTC, Chloé wrote:

The first implementation has the advantage is being simpler and 
empty being const, but has the downside that next is called 
even if the range ends up not being used. Is either approach 
used consistently across the D ecosystem?


I always go for the simplest approach. So that means, pre-fill in 
the constructor.


Yes, the downside is, if you don't use it, then the iterator has 
moved, but the range hasn't. But returning to the iterator after 
using the range is always a dicey proposition anyway.


The huge benefit is that all the functions become simple and 
straightforward.


But there is no "right" approach. And using composition, you may 
be able to achieve all approaches with wrappers. Phobos does 
various things depending on what people thought was good at the 
time. It sometimes causes some very unexpected behavior.


I recommend always using the same approach for the same library, 
that way your users know what to expect!


-Steve


Re: Statically compiled binary with C interop crashes.

2024-04-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On Thursday, 18 April 2024 at 11:05:07 UTC, yabobay wrote:
On Wednesday, 17 April 2024 at 15:24:07 UTC, Ferhat Kurtulmuş 
wrote:

On Wednesday, 17 April 2024 at 11:03:22 UTC, yabobay wrote:
I'm using [dray](https://code.dlang.org/packages/dray) in my 
project with dub, here's the relevant parts of the dub.json:


[...]


İt seems your issue is related to the raylib itself, neither 
the binding you use nor the d programming language. İnstalling 
x11 development package may resolve the issue.


I have the equivalent package installed both on the build 
machine and the machine i tried to run the code on. Also, no i 
shouldn't. It's supposed to be a statically linked binary


libglfw, which is embedded statically in raylib, is trying to 
dynamically open libx11.


https://github.com/raysan5/raylib/blob/c1fd98591d7996dd45a5ce9ecbb4b571607d417b/src/external/glfw/src/x11_init.c#L1269

So what it appears to be is, glfw tries to open a specified 
libx11, and fails, and then the program errors and exits.


The library selected is determined by a compiler directive (see 
above that line), you may have to rebuild raylib with the right 
directive based on what libx11 you have on the system.


Note, these are not *dynamically linked* libraries, but 
*dynamically loaded* libraries. That is, the system linker ldd is 
not pre-loading the library, raylib is finding the library and 
loading it at runtime.


-Steve


Re: "Error: `TypeInfo` cannot be used with -betterC" on a CTFE function

2024-04-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 14 April 2024 at 22:36:18 UTC, Liam McGillivray wrote:
On Friday, 12 April 2024 at 15:24:38 UTC, Steven Schveighoffer 
wrote:

```d
void InitWindow(int width, int height, ref string title) {
InitWindow(width, height, cast(const(char)*)title);
}
```


This is invalid, a string may not be zero-terminated. You 
can't just cast.


Well, it did work when I tried it (using a string variable, not 
a literal of course). It displayed as it is supposed to.


A cast "working" isn't enough. It could work in certain cases, 
with certain environmental conditions, etc., but fail horribly 
with memory corruption in other cases. It could even happen on 
different runs of the program. It could happen that it works 
99.999% of the time. The risk is not worth it.


But from the information I can find on the web it looks like 
strings are sometimes but not `always` zero-terminated. Not a 
great look for the language. Are there any rules to determine 
when it is and when it isn't (for string variables)?


string literals are zero-terminated. All other strings are not. 
If you have a string generated at compile time, the chances are 
good it has zero termination. However, the implicit conversion to 
`char *` is the clue that it is zero terminated. If that doesn't 
happen automatically, it's not guaranteed to be zero terminated.


A string generated at runtime only has zero termination if you 
add a 0. You should not cast to a pointer assuming the zero is 
going to be there.


Casting is a blunt instrument, which does not validate what you 
are doing is sound. A cast says "compiler, I know what I'm doing 
here, let me do this even though it's outside the language rules".



So there are a few things to consider:

1. Is the string *transiently used*. That is, does the 
function just quickly use the string and never refers to it 
again? Given that this is raylib, the source is pretty 
readable, so you should be able to figure this out.


I suppose. But if it turns out that the string is used 
continuously (as I assume to be the case with `InitWindow` and 
`SetWindowTitle`) and it doesn't make a copy of it, I imagine 
it would be difficult to design the function overload, as it 
would need to store a copy of the string somewhere. In that 
case, the only clean solution would be to have a global array 
of strings to store everything that's been passed to such 
functions, but that doesn't feel like a very satisfying 
solution. I may take a look inside some Raylib functions if I 
get back to this task.


You can pin memory in the GC to ensure it's not collected by 
using `core.memory.GC.addRoot`, which is effectively "storing in 
a global array".


2. If 1 is false, will it be saved in memory that is scannable 
by the GC? This is one of the most pernicious issues with 
using C libraries from D. In this case, you will need to 
either allocate the memory with C `malloc` or pin the GC 
memory.


You mean that the GC can destroy objects that still have 
references from the C code?


Yes. If the GC is unaware of the memory that is being used by the 
C code, it can't scan that code for pointers. It may collect 
these strings early.




For transiently used strings, I would point you at the 
function 
[`tempCString`](https://github.com/dlang/phobos/blob/0663564600edb3cce6e0925599ebe8a6da8c20fd/std/internal/cstring.d#L77), which allocates a temporary C string using malloc or a stack buffer, and then frees it when done with it.


Thank you. In a previous thread, someone told me that having to 
do many deallocations slows down the program, and the GC is 
more efficient because it deallocates many objects 
simultaneously. Is this something worth considering here, or is 
the overhead going to be tiny even when it's called a few times 
per frame?


In an *application*, I would recommend not worrying about the 
allocation performance until it becomes an issue. I'm writing a 
simple game, and never have worried about GC performance. When 
you do need to worry, you can employ strategies like 
preallocating all things that need allocation (still with the GC).


In a *general library*, you do have to worry about the 
requirements of your users. If you can allocate locally (on the 
stack), this is the most efficient option. This is what 
`tempCString` does (with a fallback to `malloc` when the string 
gets to be large).


The obvious problem in all this is to avoid accepting string 
literals (which are magic and automatically convert to const 
char *). This is currently impossible with function 
overloading, and so you need a separate function name, or put 
them in a different module.


Aren't there any compile-time conditions for this?


Unfortunately no. `string` does not implicitly convert to `char 
*` unless it is a string literal, and string literals bind to 
`string` before `char *`. So you can't rely on the overload 
working.


-Steve


Re: "Error: `TypeInfo` cannot be used with -betterC" on a CTFE function

2024-04-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 12 April 2024 at 00:04:48 UTC, Liam McGillivray wrote:

Here's what I wanted to do.

In the library I'm working on, there are various declarations 
for functions defined in an external C library following the 
line `extern (C) @nogc nothrow:`. Here are some examples of 
such declarations which have a `const(char)*` parameter:


```d
void InitWindow(int width, int height, const(char)* title);
void SetWindowTitle(const(char)* title);
Shader LoadShader(const(char)* vsFileName, const(char)* 
fsFileName);

```

I wanted to generate definitions of overloads of these 
functions using strings as parameters instead of 
`const(char)*`. For the `InitWindow` function shown above, the 
overload should be defined like this:


```d
void InitWindow(int width, int height, ref string title) {
InitWindow(width, height, cast(const(char)*)title);
}
```


This is invalid, a string may not be zero-terminated. You can't 
just cast.



or alternatively, like the following:
```d
void InitWindow(int width, int height, string title) {
InitWindow(width, height, title.toStringz);
}
```


This will allocate from the GC.

So there are a few things to consider:

1. Is the string *transiently used*. That is, does the function 
just quickly use the string and never refers to it again? Given 
that this is raylib, the source is pretty readable, so you should 
be able to figure this out.
2. If 1 is false, will it be saved in memory that is scannable by 
the GC? This is one of the most pernicious issues with using C 
libraries from D. In this case, you will need to either allocate 
the memory with C `malloc` or pin the GC memory.


For transiently used strings, I would point you at the function 
[`tempCString`](https://github.com/dlang/phobos/blob/0663564600edb3cce6e0925599ebe8a6da8c20fd/std/internal/cstring.d#L77), which allocates a temporary C string using malloc or a stack buffer, and then frees it when done with it.


The obvious problem in all this is to avoid accepting string 
literals (which are magic and automatically convert to const char 
*). This is currently impossible with function overloading, and 
so you need a separate function name, or put them in a different 
module.


-Steve


Re: How can I tell D that function args are @nogc etc.

2024-04-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 12 April 2024 at 03:57:40 UTC, John Dougan wrote:

What is the procedure for bug reporting? I'm looking at the 
issues tracker and have no clue how to drive the search to see 
if this is already there.




https://issues.dlang.org

While entering the bug title, it does a fuzzy search for existing 
open and closed issues.


-Steve


Re: How can I tell D that function args are @nogc etc.

2024-04-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On Thursday, 11 April 2024 at 03:17:36 UTC, John Dougan wrote:

Interesting. Thank you to both of you.

On Wednesday, 10 April 2024 at 17:38:21 UTC, Steven 
Schveighoffer wrote:
On Wednesday, 10 April 2024 at 11:34:06 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
Place your attributes on the right hand side of the function, 
not the left side.


Use the left side for attributes/type qualifiers that go on 
the return type.


Just a word of warning, this explanation suggests putting 
qualifiers on the left side would affect the return type, this 
is not the case.


So in my example, what did I actually tell the compiler with 
the placement of the attributes? And how was it different 
between the function type alias declaration, and the actual 
function declaration?


More specifically, what are the semantic differences below?
```d
alias FnPrefixT = @nogc nothrow @safe bool function(int);
// Versus
alias FnSuffixT = bool function(int) @nogc nothrow @safe;
```


So D can provide a nice mechanism to show what is happening -- 
`pragma(msg, ...)`


If I do that with the two types above I see something *very* 
interesting:


```d
pragma(msg, FnPrefixT);
pragma(msg, FnSuffixT);
```

```
bool function(int) nothrow @nogc
bool function(int) nothrow @nogc @safe
```

That surprises me. `nothrow` and `@nogc` go onto the type, but 
not `@safe` if put before the declaration? I have no idea why. 
All I can think of is that it is a bug.




and
```d
@nogc nothrow @safe bool fnPrefix(int) { stuff }
// Versus
bool fnSuffix(int) @nogc nothrow @safe  { stuff }
```


```d
pragma(msg, typeof(fnPrefix));
pragma(msg, typeof(fnSuffix));
```

```
nothrow @nogc @safe bool(int)
nothrow @nogc @safe bool(int)
```

(as expected)

-Steve


Re: mmap file performance

2024-04-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On Thursday, 11 April 2024 at 00:24:44 UTC, Andy Valencia wrote:
I wrote a "count newlines" based on mapped files.  It used 
about twice the CPU of the version which just read 1 meg at a 
time.  I thought something was amiss (needless slice 
indirection or something), so I wrote the code in C.  It had 
the same CPU usage as the D version.  So...mapped files, not so 
much.  Not D's fault.  And writing it in C made me realize how 
much easier it is to code in D!


For a repeatable comparison, you should provide the code which 
does 1MB reads.


I have found that mmapped files are faster than reading buffered 
files, but maybe only for large files?


-Steve


Re: "Error: `TypeInfo` cannot be used with -betterC" on a CTFE function

2024-04-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Tuesday, 9 April 2024 at 23:50:36 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

On 10/04/2024 11:21 AM, Liam McGillivray wrote:
On Sunday, 7 April 2024 at 08:59:55 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
Unfortunately runtime and CTFE are the same target in the 
compiler.


So that function is being used for both, and hence uses GC 
(appending).


Are you sure that string appending was really the problem that 
caused the "TypeInfo" build error? I forgot about this, but I 
had already had a working CTFE function with string appending 
before adding the new one that lead to this error. The symbols 
that it generates could be used in the program compiled with 
`betterC`.


No, for a string it shouldn't trigger the need for TypeInfo. 
But that wouldn't have worked regardless.


Array appending calls a runtime function which accepts `TypeInfo` 
(In this case, `TypeInfoGeneric!char`). So this does indeed 
involve `TypeInfo`. But also, even if `TypeInfo` weren't 
involved, it also needs the GC which is unavailable with betterC. 
It's just that the `TypeInfo` error happens first.


The move to use templates instead of `TypeInfo` is slowly 
happening.


-Steve


Re: How can I tell D that function args are @nogc etc.

2024-04-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Wednesday, 10 April 2024 at 11:34:06 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
Place your attributes on the right hand side of the function, 
not the left side.


Use the left side for attributes/type qualifiers that go on the 
return type.


Just a word of warning, this explanation suggests putting 
qualifiers on the left side would affect the return type, this is 
not the case.


Attributes apply to the *declaration*. In some cases this 
effectively applies to the return type, in some cases it applies 
to the function, in some cases it applies to the context pointer.


In order to apply type constructors to the return type, you need 
to use parentheses:


```d
const int  foo(); // const applies to the context pointer of 
`foo`, not `int`

const(int) bar(); // const applies to `int` return type
ref int baz(); // ref applies to `baz`, which in turn means "ref 
returning function"

```

Where this becomes tricky is return types that are function 
pointers/delegates. Then using the right side of the 
function/delegate *type* is the only way.


```d
@safe void function() foo(); // `foo` is safe, the function 
pointer it returns is not
void function() @safe bar(); // `bar` is not safe, the function 
pointer returned is

void function() @safe baz() @safe; // both are safe
```

-Steve


Re: Boneheaded question regarding compilation...

2024-04-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 1 April 2024 at 21:23:50 UTC, WhatMeWorry wrote:


Huge fan of Mike Shah's YouTube videos regarding D and his 
latest for D conference:


https://mshah.io/conf/24/DConf%20%20Online%202024%20_%20The%20Case%20for%20Graphics%20Programming%20in%20Dlang.pdf

So I installed github desktop app and cloned his Talks repo. 
There is a build command commented out at the top of the main.d 
file which I've been trying to compile, via the command line:


C:\Users\kheas\Documents\Talks\2024\dconf_online\hello_triangle>dmd -g -J. main.d 
./glad/gl/*.d -L-L/usr/local/lib -L-lglfw3 -of=prog && ./prog
Error: cannot find input file `.\glad\gl\*.d`
import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos
import path[1] = 
C:\D\dmd2\windows\bin64\..\..\src\druntime\import


I'm using a Windows 11 machine so I thought that maybe the 
syntax was for Linux environment. But replacing all the '/' 
with '\\' did not work.


Those are indeed Linux parameters and not windows compatible. 
This can’t be fixed by switching slash styles.


You need the appropriate libs and the appropriate linker switches.

-Steve


Re: Limits of implicit conversion of class arrays

2024-03-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 25 March 2024 at 07:16:35 UTC, Per Nordlöw wrote:
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

The first and second is unsound (infamously allowed in Java).


In the general case, yes. But, do you see any errors with the 
code


```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```


Yes, it's unsafe, as you can replace an element of `ds` with 
something that has no relation to `Derived`.




Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of 
the ds slice.


Again, in the general case, yes.

So what is different in this code example compared to the 
general case? Hint: this has overlaps with a missing compiler 
optimization in dmd (and many other statically typed languages) 
enabled by a specific kind of data flow analysis. Which one?


If there is a way to end up with a `Derived` reference to point 
at something that is not a `Derived` *without a cast* in system 
code, or *even with a cast* in safe code, then it is an error. It 
doesn't matter if you aren't actually doing it.


If you know you are not making that mistake, change it to system, 
and cast to inform the compiler that you "know what you are 
doing".


-Steve


Re: Unittests pass, and then an invalid memory operation happens after?

2024-03-27 Thread Steven Schveighoffer via Digitalmars-d-learn
On Wednesday, 27 March 2024 at 21:43:48 UTC, Liam McGillivray 
wrote:
In my current [game 
project](https://github.com/LiamM32/Open_Emblem), [something 
strange](https://github.com/LiamM32/Open_Emblem/issues/20) has 
happened as of a recent commit. When running `dub test`, all 
the unittests appear to pass, but then after the last unittest 
has concluded an "Invalid memory operation" happens. Removing a 
few lines replaces this error with a segfault, but either way, 
these errors shouldn't be happening. Weirdly, the commit where 
these errors first appear did nothing but replace a single 
class-member function with a seemingly identical function 
through a mixin template.


The errors seem to be related to object deletion. The traceback 
output for the first error, and where GDB points to for the 
second error, is the destructor for my `Unit` class.


You see, every `Unit` object is associated with a particular 
`Map` object and `Faction` object, which it hold references to. 
Those objects in turn each have an array of `Unit` objects that 
they are associated with. In the `Unit` destructor, I have it 
call the `removeUnit` function in both the associated `Map` and 
`Faction` objects. The errors are happening in either the 
`Unit` destructor itself, or the `removeUnit` function that it 
calls. Until the commit that introduced these errors, the 
`removeUnit` function was written directly in the `Map` class 
in it's module, but this commit replaced it with the mixin 
template `UnitArrayManagement`, which `Faction` also uses.


`Unit` destructor:
```
~this() {
this.alive = false;
if (this.map !is null) this.map.removeUnit(this);
if (this.faction !is null) 
this.faction.removeUnit(this);
if (this.currentTile !is null) 
this.currentTile.occupant = null;

}
```


The GC does not guarantee destructor order. So this code is not 
valid -- e.g. you can't count on `map` to be a valid object at 
this point.


In my estimation, the code is not correct in principle anyway -- 
if the `map` has a pointer to the `unit`, then neither will be 
collected without both being garbage, and so there is no need to 
do these calls (they are all going away presently).


The *only* thing you should be doing in a destructor is freeing 
non-GC resources.


I read that the garbage collector *sometimes* but not *always* 
calls destructors on deletion, which sounds crazy to me.


The GC is not guaranteed to delete memory or run destructors. In 
the current implementation, it will destroy everything at the end 
of the program that was allocated using the GC, but the language 
does not guarantee this.


The second error, which can be achieved by removing the 
instances of `writeln` in `removeUnit` (making it seemingly 
identical now to the version of this function previously 
defined in the `Map` class) is also strange. It seems to be a 
case of the `Unit` object calling a `Map` object that no longer 
exists. However, that's also strange, as the `Map` object is 
supposed to delete all it's associated units on destruction.


As mentioned, GCs do not work this way -- you do not need to 
worry about cascading removal of anything.


You should assume in the destructor that all references in the 
type that were pointing at GC blocks are now invalid (i.e. 
dangling pointers).




So why are these things even happening *after* the unittests 
have been run? What else do I need to know about object 
destruction? What may be happening?


The GC is cleaning up all allocated memory, in *no particular 
order*.


-Steve


Re: Reworking the control flow for my tactical role-playing game

2024-03-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 17 March 2024 at 00:14:55 UTC, Liam McGillivray wrote:
As many of you know, I have been trying to write a tactical 
role-playing game (a mix of turn-based stategy & RPG) in D. 
This is the furthest I have ever gotten in making an 
interactive program from the main function up. Right now, it is 
not yet playable as a game, but you can interact with it and 
get a rough idea of what I'm going for. Feel free to download 
and run it to see what I have so far.


https://github.com/LiamM32/Open_Emblem


I got it to run on my mac, I had to do a few updates to the 
dub.sdl file, but it did work, though I couldn't figure out how 
to make attacks work.



## The Current Structure:
The code for Open Emblem (name subject to change) is split 
between a source library, which handles the internal game 
logic, and a graphical front-end program which uses that 
library, but makes it usable.


This is kind of cool, I like the idea!


### The Library:


All sounds good


### The Raylib Front-end:
After looking at many libraries and taking a shot at 
[ae](https://github.com/CyberShadow/ae) & 
[godot-D](https://github.com/godot-d/godot-d) but not really 
figuring it out, I was recommended 
[raylib-d](https://github.com/schveiguy/raylib-d), a binding 
for [raylib](https://www.raylib.com/) by @Steven Schveighoffer. 
Raylib is a rather simple graphical library written in C. I 
ended up sticking with it because the website has so many 
easy-to-follow examples that make it easy as my first graphical 
library. They're written in, but I adapted them to D rather 
easily. Of course, being written in C has limitations as it 
isn't object-oriented.


This is front-end is in the 
[`oe-raylib/`](https://github.com/LiamM32/Open_Emblem/tree/master/oe-raylib) directory.


For this front-end, I've made the classes `VisibleTile` and 
`VisibleUnit`, which inherit `Tile` & `Unit`, but add sprite 
data and other graphics-related functionality.


I then have the `Mission` class which inherits the `MapTemp` 
class. This class dominates the program flow in it's current 
state. It handles loading data from JSON files, switching 
between different game phases and does most of the function 
calls related to rendering and input.


The way I have it currently, there's a `startPreparation` 
function and `playerTurn` function, each of which run a 
once-per-frame loop that renders all the necessary objects and 
takes user input. They each have a rather messy set of 
if-statements for the UI system. Any UI elements that may 
pop-up are declared before the loop begins, with if-statements 
to determine whether they should be visible this frame.


For UI elements, I currently have `version` flags for either 
`customgui` (which I started writing before discovering raygui) 
and `customgui`, which you can select between using `dub 
--config=`. Having both makes the code messier, but I haven't 
yet decided on which I prefer. They are both currently achieve 
equivalent functionality.


Everything here is single-threaded. Despite that, I still get 
thousands of frames-per-second when disabling the cap on 
framerate.


Note that disabling the cap on framerate just avoids the 
sleep-per-frame that raylib does. I always recommend setting a 
cap of something like 60 unless you are going to use vsync.


To get a glimpse of a flaw with the current approach (which may 
be simpler to fix with an overhaul), try asking one of the 
units to move during your turn, but then try moving the other 
unit while the first one hasn't reached their destination. The 
first unit will stop.


So when doing video game development with a main loop that needs 
to refresh the screen every frame, you need to componentize 
long-running operations into frame-size bits.


So for instance, an animation that needs to move an object from A 
to B, should be captured into a temporary item (class object, 
struct, member of the sprite, etc), where you tell it every time 
you are drawing a frame (or even better yet, each game tick), and 
let it make the changes necessary for one tick of time.


For instance, build an object that takes start position, end 
position, time to animate, and maybe a path function (like 
linear, ease-in/ease-out, etc), and then each frame calculates 
where the position should be based on the current time vs. the 
start time. Encapsulating all this into an object makes things 
easy to deal with. Then you just need to call it every frame/tick.



## Should I rework things?

So now I am thinking of reworking the rendering system, but 
also changing some of my approach to how the Open Emblem 
library works.


I've been thinking of adopting an event-driven approach, using 
signals and slots, for both the library and the front-end (and 
between the two). I'm curious if more experienced programmers 
think this is the right approach.


I'm not sure if you want to do event driven here. It's a 
possibility. But I find a game-tick system, where each tick, you 
update each object 

Re: Disable wrilten buf in docker

2024-03-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On Tuesday, 12 March 2024 at 06:36:09 UTC, zoujiaqing wrote:

Hi, my application use writeln in docker don't display.


Python add -u disable it.
https://stackoverflow.com/questions/29663459/why-doesnt-python-app-print-anything-when-run-in-a-detached-docker-container



Use setvbuf to switch to line buffering. Then you don’t have to 
manually flush everything


https://en.cppreference.com/w/c/io/setvbuf

-Steve


Re: New update fix

2024-03-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 2 March 2024 at 09:18:58 UTC, user1234 wrote:

On Saturday, 2 March 2024 at 08:41:40 UTC, Salih Dincer wrote:

SLM,

What exactly did this patch with the new update fix?


Nothing, it looks like what happened is that the issue was 
wrongly referenced by a dlang.org PR 
(https://github.com/dlang/dlang.org/pull/3701/commits/4e8db30f0bf3c330c3431e83fe8a75f843b40857).


Not wrongly referenced. The pr changed the spec to be clearer 
about the behavior. The behavior did not change.


The bug was closed as “fixed” incorrectly. I switched it to 
“wontfix”


The change log generator must have picked it up because of that.

-Steve


Re: Error when using `import`.

2024-02-26 Thread Steven Schveighoffer via Digitalmars-d-learn
On Monday, 26 February 2024 at 23:27:49 UTC, Liam McGillivray 
wrote:
I don't know whether I should continue this topic or start a 
new one now that the problem mentioned in the title is fixed. I 
have now uploaded some of the code to [a GitHub 
repository](https://github.com/LiamM32/Open_Emblem).


To make this game usable, I will need a library for graphics 
and input. I don't have any experience with making GUI programs 
aside from a little bit with Qt and C++.


If you are going for game development, I would recommend raylib-d 
(https://code.dlang.org/packages/raylib-d), which is my wrapper 
around the very good raylib library.


For doing GUI, raygui is supported, but I also can say I've seen 
some good things from fluid: https://code.dlang.org/packages/fluid


-Steve


Re: Error when using `import`.

2024-02-26 Thread Steven Schveighoffer via Digitalmars-d-learn
On Monday, 26 February 2024 at 22:40:49 UTC, Liam McGillivray 
wrote:

On Sunday, 25 February 2024 at 03:23:03 UTC, Paul Backus wrote:
You can't give a class the same name as the file it's in. If 
you do, then when you try to use it from another file, the 
compiler will get confused and think you're referring to the 
file instead of the class (that's what "import is used as a 
type" means).


Thank you. In PHP, I was told to put every class definition in 
a file of the same name (whether I like it or not).


However, I actually now have it working *without* having done 
that. Both the file name and the class name are capitalized, 
and it's working. However, maybe that's because they each start 
with a `module` line that makes the module name lowercase. I 
will keep this in mind, and maybe rename the files.


So D is weird about this. I always recommend you use a *package* 
(i.e. module foo.bar) instead of just a module (i.e. module bar).


When you omit the module declaration, the compiler assumes the 
module name is the same as the file name *without the path taken 
into account*.


What happens is if you have `Map` as a module, and then `Map` as 
the class name, using the name `Map` is going to be confusing 
(did you mean the module or the class?)


However, if you have everything under a package, for example 
`foo`, i.e. a file `foo/Map.d` which contains the `Map` class, 
then when referring to `Map`, it can't be referring to the 
module, since you would have to refer to `foo.Map` for that. This 
means the class name `Map` by itself is unambiguous.


A whole host of problems occurs with name lookup when you don't 
use packages.


-Steve


Re: The difference between the dates in years

2024-02-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Saturday, 10 February 2024 at 15:53:09 UTC, Alexander Zhirov 
wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more elegantly.


OK, so I thought this was already taking into account the day of 
the month.


This is what I came up with:

```d
int diffMonthNew(Date d1, Date d2)
{
auto diff = d1.diffMonths(d2);
if(diff > 0)
return diff + (d1.day < d2.day ? -1 : 0);
else if(diff < 0)
return diff + (d1.day > d2.day ? 1 : 0);
return 0;
}
```

Then if you want the years, it would be `diffMonthNew(d1, d2) / 
12`


-Steve


Re: The difference between the dates in years

2024-02-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Saturday, 10 February 2024 at 23:48:56 UTC, Jonathan M Davis 
wrote:


If I understand correctly, he cares about how far into the 
month the dates
are, whereas diffMonths ignores the smaller units, meaning that 
you get the

same result no matter when in the month the dates are. So,
2000-05-10 - 1990-05-09 would give 10, whereas 2000-05-10 - 
1990-05-30

would give 9. diffMonths / 12 would give 10 in both cases.


I thought `diffMonths` was actually already taking this into 
account...


Looking at the impl, it's pretty simple.

Would it make sense to have an overload that takes into account 
the day as well as the month/year? This kind of stuff is 
sometimes tricky to get right.


-Steve


Re: The difference between the dates in years

2024-02-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Saturday, 10 February 2024 at 15:53:09 UTC, Alexander Zhirov 
wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more elegantly.


Maybe I'm not understanding the question, but why not that result 
/ 12?


-Steve


Re: How to get the client's MAC address in Vibe

2024-02-08 Thread Steven Schveighoffer via Digitalmars-d-learn
On Wednesday, 7 February 2024 at 22:16:54 UTC, Alexander Zhirov 
wrote:
Is there a way to identify a client by MAC address when using 
the Vibe library?
The `NetworkAddress` 
[structure](https://vibed.org/api/vibe.core.net/NetworkAddress) 
does not provide such features. Or did I miss something?


Mac is a hardware address. By the time the packets get to your 
server, that info is long gone. Even if you could get it, it 
likely is the MAC address of your router, not the peer.


-Steve


Re: Scripting with Variant from std.variant: parameter passing

2024-02-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 2 February 2024 at 08:22:42 UTC, Carl Sturtivant wrote:
It seems I cannot pass e.g. an int argument to a Variant 
function parameter. What's the simplest way to work around this 
restriction?


You'd have to implement the function that accepts the parameters 
and wraps in a Variant.


This is the best I can come up with, which should be 
copy/pasteable to other shims:


```d
void foo(Variant x, Variant y) { ... }

import std.meta : allSatisfy;

enum isVariant(T) = is(T == Variant);

// this is going to suck at CTFE but...
string argsAsVariants(size_t count)
{
   import std.format;
   import std.range;
   import std.alglorithm;
   import std.array;
   return iota(count).map!(i => format("Variant(args[%s])", 
i).join(",");

}

// shim
auto foo(Args...)(Args args) if (!allSatisfy!(isVariant, Args))
{
mixin("return foo(", argsAsVariants(args.length), ");");
}
```

-Steve


Re: import locality with function parameters

2024-02-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 2 February 2024 at 00:29:51 UTC, Carl Sturtivant wrote:

Hello,

I seem to recall that there is surprising template to import a 
module and get a type from it inside the declaration of the 
type of a parameter to a function, so that the module need not 
be imported outside of the function definition. I think there 
was a blog article some years ago about this where there was 
some indication that this or something with equivalent effect 
would be incorporated into D in some way.


How do I define a function with a parameter that is a type in 
an outside module while keeping module import local to that 
definition?


Are you thinking of this?

https://dlang.org/phobos/object.html#.imported

-Steve


Re: Effective String to Date conversion?

2024-01-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 22 January 2024 at 10:56:04 UTC, atzensepp wrote:

Dear D-gurus,

being new to D I am trying my first steps and the language is 
quite intuitive and appealing.
When reading a file and creating a hash for the reocrds I want 
to get only the most recent ones. For this I need to convert 
Date/Time-Strings to comparable DateTime-Objects.
The code below works but looks a bit clumsy. Is there a more 
efficient (shorter) way to accomplish this?


That's how I would do it also.

I would note there also is a library I've used which works pretty 
well:


https://code.dlang.org/packages/dateparser

-Steve


Re: Safety is not what you think

2024-01-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On Tuesday, 30 January 2024 at 15:38:26 UTC, Paul Backus wrote:
This definitely isn't allowed in C or C++. I wonder what the 
rationale is for having this behavior in D?


It isn't allowed in C, but allowed in C++

https://godbolt.org/z/9xTPhsb5G

As for rationale... I don't know why it wouldn't be allowed? You 
clearly need an lvalue to use prefix ++, and the result is the 
value after adding one, so why can't it be bound to a reference? 
I don't see where the problem would arise.


-Steve


Re: Accessing array elements with a pointer-to-array

2024-01-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 26 January 2024 at 11:38:39 UTC, Stephen Tashiro wrote:

On Thursday, 25 January 2024 at 20:36:49 UTC, Kagamin wrote:
On Thursday, 25 January 2024 at 20:11:05 UTC, Stephen Tashiro 
wrote:

void main()
{
   ulong [3][2] static_array = [ [0,1,2],[3,4,5] ];
   static_array[2][1] = 6;
}


The static array has length 2, so index 2 is out of bounds, 
must be 0 or 1.


I understand that the index 2 is out of bounds in an array of 2 
things.  I'm confused about the notation for multidimensional 
arrays.  I thought that the notation uint[m][n] is read from 
right to left, so it denotes n arrays of m things in each 
array.  So I expected that static_array[k][j] would denotes the 
kth element of the jth array.


I find the following rule very straightforward to explaining it.

If you have an array, it's of type `T[]`. The `T` represents the 
type of each element. When you access element with index `n` of 
this array, it's `arr[n]`, which gives you the `n+1`th `T` 
element in the array.


So how do you match this to a static array `ulong[3][2]`? Well, 
the `T` in this case is `ulong[3]`, and the array part is `[2]`. 
So this is an array of 2 `ulong[3]`.


Therefore, when you index such an array, `static_array[2]` will 
get the 3rd element of this 2-element array, and fail.


-Steve


Re: Providing implicit conversion of

2024-01-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

The following code:

  ulong charlie = 11;
  long johnstone = std.algorithm.comparison.max(0, -charlie);
  writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 
(regardless of all arguments concerning implicit conversions, 
1's and 2's complements, being efficient, etc).


The language should not allow unary unsigned anything.


This is unlikely to get fixed, just due to the nature of D's 
philosophy when it comes to C compatibility.


It would also break a lot of existing code.

-Steve


Re: Delegates and values captured inside loops

2024-01-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 21 January 2024 at 14:52:45 UTC, Renato wrote:

On Saturday, 20 January 2024 at 16:53:12 UTC, ryuukk_ wrote:


This is the workaround according to: 
https://issues.dlang.org/show_bug.cgi?id=21929#c9


Go used to have the same issue [but they fixed 
it](https://go.dev/blog/loopvar-preview) so this is no longer a 
problem in Go.


Perhaps D could do something about it for the same reasons the 
Go blog post presented.


Actually, D is much worse. It appears in that post that local 
variables in the loop were scoped on the loop iteration, but just 
not the iteration variables themselves. This means, the machinery 
to properly capture the loop variables was trivial, just change 
the scope where those variables are allocated.


In D, there is no loop scope. So the compiler would have to 
establish a new mechanism to recognize which variables to stick 
into a closure. It's not impossible, but it is not the same scope 
as what Go had to do.


-Steve


Re: vector crash

2024-01-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On Thursday, 18 January 2024 at 03:07:13 UTC, zjh wrote:

```d
import dparse.ast;
import dparse.lexer;
import dparse.parser : parseModule;
import dparse.rollback_allocator : RollbackAllocator;
import core.stdcpp.vector;
import core.stdcpp.string;
...
```


I have no experience with using cpp from D, and I'm not sure 
exactly what you are trying to do (your code is not complete), 
but using `string` in this context does not mean C++ std::string, 
it's a D string (`immutable(char)[]`).


Are you sure this is what you are wanting to do?

-Steve


Re: `static` function ... cannot access variable in frame of ...

2024-01-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 15 January 2024 at 22:23:27 UTC, Bastiaan Veelo wrote:

On Monday, 15 January 2024 at 18:43:43 UTC, user1234 wrote:

The two calls are not equivalent.



so what is passed as alias need to be static too.


Thanks all. I thought a static member function just isn't able 
to access the instance of the struct, but as I understand now 
it is static all the way.


What I am looking for is a way to have different structs that 
have a member function that has the same name in all of them, 
that is callable without a this pointer, and able to take an 
alias argument. That is probably asking too much.



As a workaround, you can alias the outer function in the struct:

```d
struct S
{
alias foo = S_foo;
}
```

This might be less than ideal, but at least it works.

-Steve


Re: Socket handle leak and active handle warning with Vibe-D

2024-01-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 15 January 2024 at 18:40:00 UTC, bomat wrote:


Sorry, I probably should have mentioned I was on Windows.
For testing it under Linux I commented out the call to 
`connectMongoDB`, since I don't have it installed there - and 
the warning went away.
Interesting, I did not suspect that as the source of the 
problem at all. :P


I'm now looking into how to clean up MongoDB connections 
properly, but don't see anything besides `cleanupConnections()` 
(which I'm already calling without any effect).
Maybe I need to initialize it differently... I'll experiment a 
bit.


You may have to do the same thing I did with redis:

https://github.com/vibe-d/vibe.d/pull/2372

Good luck! I would also say, I don't know why Windows doesn't do 
the same trace info debug thing, except that probably whomever 
added it didn't care about windows.


-Steve


Re: Socket handle leak and active handle warning with Vibe-D

2024-01-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 15 January 2024 at 17:24:40 UTC, bomat wrote:
On Sunday, 14 January 2024 at 20:36:44 UTC, Steven 
Schveighoffer wrote:
There should be a version you can enable that tells you where 
that socket handle was allocated. That might give you a 
further clue as to why it's not closed when the system shuts 
down.


I think the program tells you which version to enable when 
this happens, but if not, let me know and I'll find it.


Thanks for the response, Steve.
Hmmm, not sure if I'm missing something, but this is all the 
output I get from the program:

```
[main() INF] Listening for requests on http://[::1]:8080/
[main() INF] Listening for requests on 
http://127.0.0.1:8080/

[() INF] Received signal 2. Shutting down.
[main() INF] Stopped to listen for HTTP requests on ::1:8080
[main(
) INF] Stopped to listen for HTTP requests on 127.0.0.1:8080
Warning: 1 socket handles leaked at driver shutdown.
Warning: 1 socket handles leaked at driver shutdown.
```
Unless there's some switch to make it more verbose?


Which driver are you using? In the posix driver, it should 
mention (and use) the debug flag `EventCoreLeakTrace`.


https://github.com/vibe-d/eventcore/blob/7fa0a15fa541c3fcf65640ee332fd3a09c34730c/source/eventcore/drivers/posix/driver.d#L130

I didn't realize this wasn't across the board...

-Steve


Re: Socket handle leak and active handle warning with Vibe-D

2024-01-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 13 January 2024 at 20:49:54 UTC, bomat wrote:

I am still getting this in 2024 and vibe.d 0.9.7:
```
Warning: 1 socket handles leaked at driver shutdown.
```

I was wondering if maybe someone has new info on this...


There should be a version you can enable that tells you where 
that socket handle was allocated. That might give you a further 
clue as to why it's not closed when the system shuts down.


I think the program tells you which version to enable when this 
happens, but if not, let me know and I'll find it.


-Steve


Re: Non-blocking keyboard input

2024-01-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 14 January 2024 at 13:41:26 UTC, Joe wrote:

This does not actually work on my computer. It still blocks.


Adam is no longer using mainstream D, and apparently not posting 
on this forum.


I suggest you try to contact him via the arsd github page:

https://github.com/adamdruppe/arsd

-Steve


Re: Synchronisation help

2024-01-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 1 January 2024 at 15:48:16 UTC, Anonymouse wrote:
What is the common solution here? Do I add a module-level 
`Object thing` and move everything accessing the AA into 
`synchronized(.thing)` statements? Or maybe add a `shared 
static` something to `Foo` and synchronise with 
`synchronize(Foo.thing)`?


Yeah, and the thing should be a `Mutex` object. A `Mutex` object 
uses it's underlying mutex primitive as its monitor. This also 
gives options for usage with methods as well as `synchronized` 
statements.


Just make sure you mark it `__gshared` or `shared` so all threads 
see it.


-Steve


Re: jsoniopipe - exaples?

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

On Friday, 29 December 2023 at 08:09:58 UTC, Zz wrote:

Hi,

Here are some samples from the std.json documentation.
Any idea on how to do something similar using jsoniopipe?

Directly copied from https://dlang.org/phobos/std_json.html

import std.conv : to;

// parse a file or string of json into a usable structure
string s = `{ "language": "D", "rating": 3.5, "code": "42" }`;
JSONValue j = parseJSON(s);
// j and j["language"] return JSONValue,
// j["language"].str returns a string
writeln(j["language"].str); // "D"
writeln(j["rating"].floating); // 3.5

// check a type
long x;
if (const(JSONValue)* code = "code" in j)
{
if (code.type() == JSONType.integer)
x = code.integer;
else
x = to!int(code.str);
}

// create a json struct
JSONValue jj = [ "language": "D" ];
// rating doesnt exist yet, so use .object to assign
jj.object["rating"] = JSONValue(3.5);
// create an array to assign to list
jj.object["list"] = JSONValue( ["a", "b", "c"] );
// list already exists, so .object optional
jj["list"].array ~= JSONValue("D");

string jjStr = 
`{"language":"D","list":["a","b","c","D"],"rating":3.5}`;

writeln(jj.toString); // jjStr


jsoniopipe is not focused on the `JSONValue` 
[equivalent](https://github.com/schveiguy/jsoniopipe/blob/7d63a2e19ae46a1ae56ccab4c6c872bcce094286/source/iopipe/json/dom.d#L22)


You can see it's pretty basic and just serves as a "catch any 
type" thing.


It could easily be replaced with `std.json.JSONValue`, though I 
like the fact that it's templated on the string type.


The main focus of jsoniopipe is parsing and serialization -- I 
prefer to use real concrete structs/classes rather than variant 
types. In fact, the huge benefit from the library is that there 
is no intermediate type.


But yeah, I could ingest all the functionality from std.json 
there. Or maybe even just use `JSONValue` from std.json. Could 
you make an issue?


-Steve


Re: How to get serve-d to find dub dependencies

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

On Saturday, 23 December 2023 at 16:28:28 UTC, Renato wrote:

On Saturday, 23 December 2023 at 16:13:01 UTC, Renato wrote:

I am trying to use dependencies, so I need dub.

On emacs, the imports from dub libraries cannot be found, even 
though dub can build it fine.


How can I get emacs/serve-d to "see" the libraries added by 
dub?


I found that dub has a command for letting the compiler know 
about the load paths:


```
dub describe --data=import-paths
```

This shows the correct paths for the project, so perhaps I can 
pass this to serve-d somehow?


I've managed to kind of hack it by adding the paths to my 
`.dir-locals.el`:


```
((nil . ((indent-tabs-mode . nil)
 (tab-width . 4)))
 (d-mode . ((compile-command . "dmd -L-ld_classic -run")
(eglot-workspace-configuration . (:importPath 
("/Users/renato/.dub/packages/console-colors/1.1.1/console-colors/source/"))

```

Far from ideal but this makes it half work... it actually shows 
the definitions in the library now and I can even navigate to 
the source, but still for some reason the import is shown as an 
error:


```
Expected 'consolecolors.d' or 'consolecolors/package.d' in one 
of the following import paths:

```

I believe that's because this is coming from d-mode, not 
serve-d (as serve-d actually "sees" it now)?!


Anyway, would love to know how to get serve-d to automatically 
detect dub libs.


dub recently changed how it stores packages. serve-d uses dub as 
a library to figure this out, so if the dub version serve-d is 
linked against does not match the version of dub you use to 
install/build, then it won't find the library includes.


Check your version of dub against the version of dub serve-d is 
building against.




Does the VS Code do that? If it does, this should work also on 
emacs.


VS Code has a similar problem if you have a mismatch. The 
solution is to use the beta/nightly release channel of serve-d if 
you have a recent compiler.


I will note there are some packages that serve-d just can't 
figure out for imports, because the configuration is done via 
dflags.


-Steve


Re: Operator "+=" overloading for class?

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

On Monday, 18 December 2023 at 14:38:14 UTC, Ki Rill wrote:

your code just return result value,
but it should not return but save result to "this"
see example at 
https://dlang.org/spec/operatoroverloading.html#index_op_assignment


I get an error, but don't understand why.
```d
auto opOpAssign(string op)(Value rhs)
{
this = this + rhs;
return this;
}

// Error: `this` is not an lvalue and cannot be modified
```


Assigning an object is like copying a pointer. You may think you 
can try overloading the assignment, but it is 
[forbidden](https://dlang.org/spec/operatoroverloading.html#assignment):


```
However for class types, identity assignment is not allowed. All 
class types have reference semantics, so identity assignment by 
default rebinds the left-hand-side to the argument at the right, 
and this is not overridable.

```

But you aren't trying to do this.

Instead you are trying to reassign the `this` reference, which is 
a local (and also forbidden). Think about it a second, your `this 
+ rhs` is going to allocate a *new* object. Then if the 
assignment to the local `this` parameter succeeded, what happens 
outside the member function? The true reference that is calling 
this will not be updated!


The only way to do this I can see is to reimplement for op=, or 
maybe perform the operation and swap the guts out.


-Steve


Re: Manually relesing memory

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

On Saturday, 9 December 2023 at 10:12:11 UTC, Vlad Stanimir wrote:
I am new to the language and am curios about manual memory 
management options.


From what i can tell dlang offers the option for both manul and 
automatic management of memory resources.





You might find all the answers in this blog series

https://dlang.org/blog/the-gc-series/

-Steve


Re: now I need -allinst when dmd compiles the unittest

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

On Friday, 1 December 2023 at 22:00:52 UTC, kdevel wrote:
If I not use -allinst the linker complains when using the 
current msgpack-d v1.0.5, e.g.


[...]msgpack-d/src/msgpack/package.d:203: undefined reference 
to `pure nothrow @nogc @safe immutable(char)[] 
core.internal.dassert._d_assert_fail!(int)._d_assert_fail!(int)._d_assert_fail(scope const(immutable(char)[]), scope ref const(int), scope ref const(int))'


[...]msgpack-d/src/msgpack/packer.d:1326: undefined reference 
to `pure nothrow @nogc @safe immutable(char)[] 
core.internal.dassert._d_assert_fail!(const(int))._d_assert_fail!(int)._d_assert_fail(scope const(immutable(char)[]), scope ref const(int), scope const(int))'


[...]/msgpack-d/src/msgpack/unpacker.d:1505: undefined 
reference to `pure nothrow @nogc @safe immutable(char)[] 
core.internal.dassert._d_assert_fail!(int)._d_assert_fail!(int)._d_assert_fail(scope const(immutable(char)[]), scope ref const(int), scope ref const(int))'


Are you using -checkaction=context? I have discovered that this 
happens if you build with -checkaction=context, but druntime has 
not been built with it, or you are using betterC.


What happens is that an assert failure will trigger a call to a 
druntime function, and the compiler thinks that function is 
already instantiated in druntime, so it skips emitting the 
function, and expects druntime to be linked.


I'm unsure whether druntime has the appropriate checkaction 
functions built by default, but definitely if you use betterC it 
won't be linked.


For reference:

https://issues.dlang.org/show_bug.cgi?id=22374
https://issues.dlang.org/show_bug.cgi?id=22902
https://issues.dlang.org/show_bug.cgi?id=19937

You even reported one of these...

-Steve


Re: Advent of Code 2023

2023-12-03 Thread Steven Schveighoffer via Digitalmars-d-learn
On Sunday, 3 December 2023 at 18:56:32 UTC, Johannes Miesenhardt 
wrote:
On Sunday, 3 December 2023 at 14:51:37 UTC, Siarhei Siamashka 
wrote:

[...]


Thanks, this is super helpful. I have one other question, in 
the solution you posted and also the one I posted in the 
discord today. I was required to use byLineCopy. I first used 
byLine but I for some reason that I can't really explain only 
got the last line from that. I switched to byLineCopy because I 
saw it in other peoples solution and that magically fixed all 
problems I had. What exactly happened here?


byLine reuses the buffer. So it is only valid while you haven’t 
fetched the next line.


byLineCopy makes a copy of the line to give you so it will always 
remain valid.


In these simple small type problems I find it easier to just 
fetch the whole file into a string and work with that. The 
performance of parsing the input is negligible.


-Steve



Re: msghdr and cmsghdr mismatch for alpine musl

2023-11-26 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 25 November 2023 at 05:04:57 UTC, d007 wrote:

`import core.sys.posix.sys.socket : msghdr, cmsghdr, iovec;`


`msg_iovlen`, `msg_controllen`, `cmsg_len` is ulong for x86-64 
in druntime.




in alpine musl, they are int,  socklen_t(uint), socklen_t(uint).



Is this mismatch can cause problems is I use related api ?


Yes. Mismatch of types is a really bad error for c interaction.

-Steve


Re: Dirty DMD

2023-11-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 18 November 2023 at 18:52:07 UTC, JN wrote:
Latest DMD for Windows downloaded from here: 
https://downloads.dlang.org/releases/2.x/2.105.3/dmd-2.105.3.exe reports version as dirty:


DMD64 D Compiler v2.105.3-dirty
Copyright (C) 1999-2023 by The D Language Foundation, All 
Rights Reserved written by Walter Bright


what does it mean by dirty?


Something in the build process changes a file and therefore the 
thing that checks the version marks it as dirty. It’s perfectly 
fine, this is the official release.


It’s a bit embarrassing to be honest. The windows binaries have 
been reporting dirty for years and nobody cares to fix it.


-Steve



Re: D: How to check if a function is chained? a().b().c();

2023-11-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 18 November 2023 at 07:47:19 UTC, BoQsc wrote:

Let's say we have a chain of functions.
```
 a().b().c();
```


I would like to have a behaviour in `a()` that would check if 
there is `b()` or `c()` chained to it.


If `a();`is not chained: do a `writeln("You forgot to chain 
this function!");`


 A function that executes a program

For me syntactically it is important. One real world 
application would be:


`program("someProgramName").pipe("someOtherProgramName");`
Executes and pipes output to another program.

`program();` - Only executes the program.


Consider adding @mustuse on the return type.

https://dlang.org/spec/attribute.html#mustuse-attribute

-Steve



Re: Struct copy constructor with inout

2023-11-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On Tuesday, 14 November 2023 at 13:58:17 UTC, Paul Backus wrote:

It's easier to see if you compare the actual and expected 
argument lists side-by-side


Expected: (ref const(S1) s) const
Actual:   (const(S1)  )
^
 Mismatched 'this' argument


This would be a much better output. Is this something you made up 
or did you get it from one of the compilers? LDC2, which is what 
I tested with, reported in the format that I mentioned.


It might be something to add to the compiler that mismatches in 
`this` qualifiers should be reported separately, especially since 
the mutable form has no explicit qualifier. But I guess this is 
only an issue for constructors, because normal const functions 
can be called with mutable objects.


That being said, I still consider this a bug, if the inout 
version works, the const version should work as well. I don't see 
the difference.


So an interesting thing, if I change the `int i` to `int *i` in 
`S2`, instead of compiling I get the error:


```
Error: `inout` constructor `testinoutctor.S2.this` creates const 
object, not mutable

```

Which gives a much nicer error message!

-Steve


Re: Struct copy constructor with inout

2023-11-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On Tuesday, 14 November 2023 at 08:50:34 UTC, dhs wrote:


I am using following code:

```d
struct S1
{
this(ref const S1 s) const { writeln("copy"); }
int i;
}

struct S2
{
this(ref inout S2 s) inout { writeln("copy"); }
int i;
}

void test()
{
const(S1) s1;
S1 ss1 = s1; // error, ss1 not qualified as const

const(S2) s2;
S2 ss2 = s2; // fine, why?
}
```

Isn't "inout" supposed to copy the const-ness of its parameter 
to the constructor's attribute? In other words: why doesn't 
ss2=s2 fail here?



`ss2 = s2` does not fail because the type is implicitly 
convertible to non-const (a const int can be converted to a 
mutable int). Change `i` to `int *` and it will fail.


IMO, the first should succeed as well. And I will note that the 
error looks different from what you say:


```
Error: copy constructor `testinoutctor.S1.this(ref const(S1) s) 
const` is not callable using argument types `(const(S1))`

```

I'm not sure what this means. There shouldn't be a copy being 
made here, as the thing is already const. I don't understand this 
error, and it looks like a bug to me.


-Steve


Re: Dlang installer with VSCode broken

2023-11-05 Thread Steven Schveighoffer via Digitalmars-d-learn
On Sunday, 5 November 2023 at 22:28:29 UTC, Daniel Donnelly, Jr. 
wrote:


This is on my friend's machine, who I am teaching D.   What can 
be done?



Can you describe what you did? Also, might be helpful to file an 
issue on the code-d github repository itself:


https://github.com/Pure-D/code-d

-Steve


Re: Convert String to Date and Add ±N Hours

2023-11-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 4 November 2023 at 18:11:53 UTC, Vahid wrote:

Hi,

I have a date string with the format of "2023-11-04 23:10:20". 
I want to convert this string to Date object and also, add ±N 
hours to it. For example:


`"2023-11-04 23:10:20" + "+2:00" = "2023-11-05 01:10:20"`
`"2023-11-04 23:10:20" + "-2:30" = "2023-11-05 20:40:20"`

How can I do this?


Parse the date. There is a nice package on code.dlang.org that is 
for date parsing: https://code.dlang.org/packages/dateparser


-Steve


Re: why remove octal literal support?

2023-11-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 3 November 2023 at 15:07:41 UTC, d007 wrote:
dlang is know for compile speed,  but in reality d project 
compile slow because so much ctfe and tempalte.



Why bring more ctfe call by remmove octal literal ?


octal literals are extremely error prone, because people 
sometimes use leading zeroes for alignment, not realizing that it 
means the number is completely different.


Actual correct octal literal use is vanishingly small. Banning 
C-style octal literals just makes it so the compiler flags 
unintended errors like this.


-Steve


Re: What are the best available D (not C) File input/output options?

2023-11-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On Thursday, 2 November 2023 at 15:46:23 UTC, confuzzled wrote:

I tried std.io but write() only outputs ubyte[] while I'm 
trying to output text so I abandoned idea early.


Just specifically to answer this, this is so you understand this 
is what is going into the file -- bytes.


You should use a buffering library like iopipe to write properly 
here (it handles the encoding of text for you).


And I really don't have a good formatting library, you can rely 
on formattedWrite maybe. A lot of things need to be better for 
this solution to be smooth, it's one of the things I have to work 
on.


-Steve


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: T[] opIndex() Error: .. signal 11

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

On 10/5/23 1:49 AM, ag0aep6g wrote:

For some further reading, there's an open issue about the unexpected 
slicing: https://issues.dlang.org/show_bug.cgi?id=14619


Thank you I had forgotten about that issue!

-Steve


Re: T[] opIndex() Error: .. signal 11

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

On 10/3/23 11:12 AM, Joel wrote:
The following program crashes, but doesn’t if I change (see title) T[] 
to auto. The program doesn’t even use that method/function. What’s the 
story?


It's a stack overflow.

when doing foreach on your type, the compiler *always* uses a slice 
first if it compiles and is a valid range.


So `foreach(x; ints)` really translates to `foreach(x; ints[])`.

Normally not a problem. But your `opIndex()` is calling `this.array`. 
What does `this.array` do? a foreach on your type. Which calls 
`opIndex`, which calls `array`, which calls `opIndex`, etc.


When you make it auto, well, then inside the `array` function, it won't 
use the `opIndex` (because clearly, the type hasn't been determined). 
And so it goes with the range functions without first doing a slice.


But then outside the type, now that `opIndex` type has been inferred, it 
can now use `foreach(x; ints[])`, and that goes back to the regular 
mechanism.


A minimized case is here:

```d
struct S
{
int front() => 1;
void popFront() {}
bool empty() => true;

auto opIndex() {
foreach(x; this) {}
return int[].init;
}
}

void main()
{
S s;
foreach(x; s) {}
}
```

If you run this on run.dlang.io, and click the "AST" button, you will 
get this for the type and the main function:


```d
import object;
struct S
{
int front()
{
return 1;
}
void popFront()
{
}
bool empty()
{
return true;
}
auto @system int[] opIndex()
{
{
S __r2 = this;
for (; !__r2.empty(); __r2.popFront())
{
int x = __r2.front();
}
}
return null;
}
}
void main()
{
S s = 0;
{
scope int[] __r3 = s.opIndex()[];
ulong __key4 = 0LU;
for (; __key4 < __r3.length; __key4 += 1LU)
{
int x = __r3[__key4];
}
}
return 0;
}
```

Note the difference in how the foreach code is lowered. Inside 
`opIndex`, it's lowered to the range functions. Outside, it uses the 
slice operator to switch to iterating a `scope int[]`.


If you now switch the `auto` to `int[]`, it's a segfault, because now 
the `opIndex` has a concrete return type, and it *can* use the 
`opIndex`, inside `opIndex`.


I really think the implicit slice should be revisited. It shouldn't 
happen in this case.


-Steve


Re: The difference between T[] opIndex() and T[] opSlice()

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

On 10/3/23 12:09 PM, Paul Backus wrote:

On Tuesday, 3 October 2023 at 13:07:00 UTC, Steven Schveighoffer wrote:


Now, you can define a further `opIndexAssign(T val, size_t idx)`. 
However, now you lose capabilities like `a[0]++`, which I don't think 
has a possibility of implementing using an `opIndex` operator, and it 
would be pretty ugly if you had to.


Works for me, with both `++` and `+=`: https://run.dlang.io/is/JckTVG

AST output confirms that these are lowered to use `opIndex`.

Looking at the spec, it seems like `opIndex` would only be pre-empted 
here if you overloaded `opIndexUnary` (for `++`) and/or 
`opIndexOpAssign` (for `+=`).


OK, so it's not as bad as I thought, but surely the compiler should 
recognize that `opIndexAssign(val, idx)` doesn't work, but `opIndex(idx) 
= val` does?


-Steve


Re: The difference between T[] opIndex() and T[] opSlice()

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

On Monday, 2 October 2023 at 20:42:14 UTC, Paul Backus wrote:

On Monday, 2 October 2023 at 20:34:11 UTC, Salih Dincer wrote:
In an old version (for example, v2.0.83), the code you 
implemented in the places where Slice is written above works 
as desired.  In the most current versions, the parameterized 
opIndexAssign(T value) gives the error:


onlineapp.d(51): Error: function 
`onlineapp.Matrix!double.Matrix.opIndexAssign(double value)` 
is not callable using argument types `(double, ulong)`

onlineapp.d(51):expected 1 argument(s), not 2


**Source:** https://run.dlang.io/is/TPAg5m


I don't know what's wrong in your example but this works for me:

```d
struct S
{
void opIndexAssign(int value)
{
import std.stdio;
writeln("assigned ", value);
}
}

void main()
{
S s;
s[] = 7;
}
```


So in the example linked by Salih, the `opIndex` returns a ref, 
which is a valid mechanism to properly do `a[0] = val;`. However, 
since `opIndexAssign` exists, the compiler expects that to be 
used instead.


Essentially, by naming the slice assign the same operator as 
index assign, you have eliminated the possibility for ref 
assignment via indexing.


Now, you can define a further `opIndexAssign(T val, size_t idx)`. 
However, now you lose capabilities like `a[0]++`, which I don't 
think has a possibility of implementing using an `opIndex` 
operator, and it would be pretty ugly if you had to.


This seems like a design flaw in the `opIndex` overloading 
changes. I would stick with `opSliceAssign` if faced with this 
problem (glad it still works!)


It could also be considered a bug but I don't know the overload 
implications.


-Steve


Re: The difference between T[] opIndex() and T[] opSlice()

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

On 10/1/23 1:41 PM, Salih Dincer wrote:

Hi,

What is the difference between T[] opIndex() and T[] opSlice(), which 
haven't parameters?


None. It used to be that opSlice was the only way, and the mechanisms 
opSlice uses are still valid.


-Steve


Re: Straight Forward Arrays

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

On 10/1/23 1:13 PM, dhs wrote:

It may not be a problem in practice. My concern was performance, because 
each time we add an element to the array, the garbage collector has to 
map the slice to the allocation it belongs to.


FWIW, there is a cache that makes this decently fast, so it doesn't have 
to go all the way into the GC to get all the information for every append.


But it *most definitely* not going to be as fast as reading a local 
"capacity" variable.


-Steve


Re: Straight Forward Arrays

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

On 10/1/23 10:34 AM, Steven Schveighoffer wrote:



The complexity is from the way d does operator overloading and indexing.

It should be pretty straightforward. I’ll see if I can post a simple 
wrapper.


I didn't tackle any attribute or memory safety issues, or many operator 
overloads, but this is going to be reasonably close. It should make a 
copy of the data when copied.


Note this still uses the GC for storage, and when expanding, uses the GC 
to fetch the capacity (this could be done in one call, but meh).


Some niceties of builtin arrays may not work, but this is somewhat of 
the cost you pay for trying to make a custom type.


```d
struct VTArray(T)
{
private T[] _storage;
private size_t _length;

const size_t length() => _length;

void length(size_t newLen) {
if(newLen <= _storage.length)
_length = newLen;
else
{
_storage.length = newLen;
_storage.length = _storage.capacity;
}
}

inout this(ref inout(VTArray) other)
{
this(other[]);
}

inout this(inout(T)[] buf)
{
auto x = buf.dup;
x.length = x.capacity;
_length = buf.length;
_storage = cast(inout)x;
}

ref inout(T) opIndex(size_t idx) inout {
assert(idx < length);
return _storage[idx];
}

void opOpAssign(string s : "~", V)(auto ref V other) {
static if(is(V == T[]))
{
immutable avail = _storage.length - length;
if(avail < other.length)
{
_storage[length .. $] = other[0 .. avail];
_storage ~= other[avail .. $];
_storage.length = _storage.capacity; // expand to capacity;
}
else
{
_storage[length .. length + other.length] = other;
}
_length += other.length;
}
else static if(is(V == T))
{
if(length == _storage.length)
{
_storage.length += 1;
_storage.length = _storage.capacity;
}
_storage[_length++] = other;
}
else static if(is(V == VTArray))
{
this ~= other[];
}
}

void opAssign(T[] arr)
{
_storage = arr.dup;
_storage.length = _storage.capacity;
_length = arr.length;
}

void opAssign(VTArray vtarr)
{
this = vtarr._storage[0 .. vtarr.length];
}

inout(T)[] opIndex() inout => _storage[0 .. _length];

void toString(Out)(auto ref Out output)
{
import std.format;
formattedWrite(output, "%s", this[]);
}
}

void main()
{
auto arr = VTArray!int.init;
arr ~= 1;
arr ~= [2,3,4,5];
import std.stdio;
writeln(arr);
auto arr2 = arr;
arr2[0] = 5;
writeln(arr);
writeln(arr2);
arr2 ~= arr;
writeln(arr2);
}
```

This should give you a reasonable head-start.

-Steve


Re: Straight Forward Arrays

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

On Sunday, 1 October 2023 at 13:24:27 UTC, dhs wrote:
On Sunday, 1 October 2023 at 13:05:12 UTC, Steven Schveighoffer 
wrote:

On Sunday, 1 October 2023 at 09:01:53 UTC, dhs wrote:

[...]


Std::vector uses value semantics. D does not have anything 
like that. It could be done someone just has to do it.


Yes, and therein lies the problem: writing a dynamic array is 
not a very difficult task for an old developer like me. I 
looked at the D runtime and at the Phobos implementation for 
reference. The code is so extremely difficult to understand and 
uses so many advanced D features, that I doubt that I am up to 
the task. For me, the point of switching to D was to use a 
language that is simpler to read and maintain.


The complexity is from the way d does operator overloading and 
indexing.


It should be pretty straightforward. I’ll see if I can post a 
simple wrapper.


-Steve


Re: Straight Forward Arrays

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

On Sunday, 1 October 2023 at 09:01:53 UTC, dhs wrote:

Hi,

Is there a straight forward Array type in D similar to C++'s 
vector class? Something along the lines of the tuple: (pointer 
to elements, length, capacity).


[...]


Std::vector uses value semantics. D does not have anything like 
that. It could be done someone just has to do it.


-Steve


Re: Vibe.d download function, how to get callback when done or error?

2023-09-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/23 8:07 AM, j...@bloow.edu wrote:

I'm using download(url, filename) to download files in vibe.d.

The issue is that I do not know when the download is finished or errors. 
There is a callback for the streaming side but not for the file download.




You might misunderstand how vibe is doing async. Basically, that fiber 
is put to sleep until the download is finished, and then you get the 
result. You write your code as if it were synchronous.


If you call this outside of an async context, vibe will start up an 
event loop and run it until your download is done.


-Steve


Re: range shortened method not enabled, compile with compiler switch `-preview=shortenedMethods`

2023-09-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 24 September 2023 at 10:00:31 UTC, Joe wrote:

For absolutely no reason I started getting this error.

Last night I compiled the project and it worked just fine. This 
morning I made a single insignificant change and tried to 
compile and got that error. Only possible thing is that for 
some reason some change in updating the compiler may have no 
propagated correctly till after the reboot.


[...]


This sounds like a compiler issue. Are you on the latest 
compiler? Which compiler? Is there a set of code you can post or 
upload which causes the problem?


-Steve


Re: "readln" after "readf"

2023-09-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On Thursday, 21 September 2023 at 09:14:14 UTC, pascal111 wrote:
I've a problem when I'm using "readln" after "readf" that I 
couldn't see my program rest and the lines of the execution ran 
fast:


module main;

import std.stdio;
import std.string;
import std.conv;

int main(string[] args)
{

char[] yy;
int x,y,z;


writef("Enter a number: ");
readf(" %d",);


writef("Enter a number: ");
readf(" %d",);

z=x+y;
writefln("Hi! %d",z);

writef("Enter a number: ");
readln(yy);
yy = strip(yy);
x=to!int(yy);

writef("Enter a number: ");
readln(yy);
yy = strip(yy);
y=to!int(yy);

z=x+y;
writefln("Hi! %d",z);

return 0;
}


Your readfs are not consuming the newline at the end. Add `\n` to 
the end of the format text.


-Steve



Re: How to use core.vararg to print D variadic arguments and their types without using ! (template instantiation)?

2023-09-16 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/15/23 4:14 PM, Basile B. wrote:

On Thursday, 14 September 2023 at 15:19:29 UTC, BoQsc wrote:

https://dlang.org/phobos/core_vararg.html

The common way to use **va_arg** is `va_arg!(int)(_argptr);`
What would be the alternative way or syntax that behave exactly the 
same way, even if more verbose?





`va_arg!(int)(_argptr);` is taken from an example in:
https://dlang.org/spec/function.html#d_style_variadic_functions


here's how

```d
import core.vararg;

void main()
{
     foo(.5, 5);
}

void foo(...)
{
     int i = void;
     va_arg(_argptr, typeid(i), );
     assert(i == 5);
     double d = void;
     va_arg(_argptr, typeid(d), );
     assert(d == .5);
}
```


Note that this doesn't work in gdc.

The templated version is actually more akin to what C does.

-Steve


Re: Setting struct as default parameter of a function using struct literal?

2023-09-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 11 September 2023 at 19:59:37 UTC, ryuukk_ wrote:



I would love to be able to use C style designated 
initialization everywhere too..


Recent version of D added named arguments so you can do 
something like:


```D
void someFunction(Options option = Options(silenceErrors: 
false))

```

I don't like the useless repeating "option option option", but 
that's D for you



```d
void someFunction(bool silenceErrors = false, bool otherOption = 
true)


someFunction(otherOption: false); // works
```

I know options structs have benefits besides allowing parameter 
specification, but with the latest allowance of named parameters, 
it's worth exploring whether you still want to use an options 
struct or not.


-Steve


Re: malloc error when trying to assign the returned pointer to a struct field

2023-09-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On Saturday, 9 September 2023 at 09:21:32 UTC, rempas wrote:

Now, if only one could expect how and why "libc" knows that and 
doesn't just care to give me the memory I asked it for? Or it 
could be than D does something additional without telling us? 
Which can explain when this memory is only present when I 
assign the value to the "this._ptr` field!




You are focusing on the wrong problem.

You asked for size bytes, and malloc gave you size bytes. It 
doesn't "know" anything special.


Then you proceeded at some point to write *past* the size bytes. 
What did you overwrite? Probably some internal malloc 
implementation structure. Then it later noticed "hey, this 
structure doesn't make sense, I'm going to report it to the 
user!" That's why you see the message.


Memory problems are very difficult to find, and typically an 
error is triggered far away from the source, in seemingly 
unrelated code. This is why whenever I see an error that smells 
like memory corruption, I stop all other work and find it. Memory 
errors can come and go based on random chance or how the compiler 
lays out functions. So having it "just go away" isn't enough. 
Very very infrequently, this happens because of a codegen issue, 
but most of the time it's pilot error.


-Steve


Re: malloc error when trying to assign the returned pointer to a struct field

2023-09-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On Friday, 8 September 2023 at 07:59:37 UTC, rempas wrote:

I do have the following struct:


...

That's some minimal code that I do have just to showcase it.


This is not ideal. Why? Because 99% of the time, a poster has 
come here with a problem they don't know how to solve, and have 
focused in on where they *think* the problem is. However, the 
problem isn't there. But us reading the description can only see 
what the poster sees, and either don't see a problem ("I'm just 
as confused as you are!") or know there is more to the story.


Not only that, but frequently not-complete code is... not 
complete. And people tend to focus on problems they can see (e.g. 
where is that `_len` defined?), frustrating the poster with 
"trivial" problems that are solved "in the real code".


Inevitably, there is a subsequent post with the real code, and 
that contains the problem.


The best thing to post is a minimally reproducing example. The 
next best thing is a link to a complex reproducing example. Which 
you have done later (I will take a look). I just wanted to point 
this out because it's a frequent problem on these forums.


So, some times, this work will works, some others, it will give 
me the following error:


`Fatal glibc error: malloc.c:2594 (sysmalloc): assertion 
failed: (old_top == initial_top (av) && old_size == 0) || 
((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) 
&& ((unsigned long) old_end & (pagesize - 1)) == 0)`


This is an internal message from glibc. It seems the malloc 
structure is corrupted.


Is there any possible that there is a compiler bug? I do use 
ldc2 and `betterC`!


There is always a chance...

Now, critiquing your original code, I see red flags here:


```d
  u64 _cap = 0;   // Total amount of elements (not bytes) we 
can store

```


and then later:


```d
  this(i64 size) {
this._len = 0;
this._cap = size;
```


ok, so `size` must mean the number of elements, not the number of 
bytes.



```d
static if (is(T == char)) { size += 1; } // Additional 
space for the null terminator

this._ptr = cast(T*)malloc(size);
```


Here, you have allocated `size` bytes for the array. Is this what 
is intended? Your comments suggest otherwise! If `T.sizeof` is 2 
or more, then you still only allocate e.g. 20 bytes for a `_cap` 
of 20. but an array of 20 T's would require 40 bytes.


-Steve


Re: AA vs __gshared

2023-08-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/12/23 5:55 AM, IchorDev wrote:

On Thursday, 10 August 2023 at 15:20:28 UTC, Steven Schveighoffer wrote:

That shouldn't matter.


Well, it does here. The AA is mutated during the loop, so perhaps this 
is an optimisation quirk where it works with `for` but segfaults in 
`foreach`? I've pretty thoroughly abused the `for` version and I haven't 
gotten it to segfault yet.


oh yeah. That is not allowed. Any mutation of the AA during iteration 
can invalidate existing foreach or ranges over the AA.


Basically, a rehash can cause the buckets to jumble up, and in that 
case, the "current index" can be changed to point at a null bucket.


More here: https://dlang.org/spec/statement.html#foreach_restrictions

In fact, that statement is way too broad. Invalidation of iteration 
should be based on the type's requirements.


We really should put a note in the AA spec page.

I also highly recommend using `emplace` to handle all the sticky 
issues with lifetime/construction.


Have not run into the aforementioned sticky issues yet, but I can't even 
find `emplace`'s docs anywhere now.


https://dlang.org/phobos/core_lifetime.html#.emplace

I recall it being incompatible with 
classes that have @nogc/nothrow constructors though, which made it 
pretty useless to me, and it wouldn't work with BetterC, which was a 
requirement for the allocation wrapper I was writing at the time.


It probably won't work with betterC, but that's probably just because of 
linker errors.


Any attribute requirements would be inferred based on the attributes of 
your constructor, because emplace is a template.


-Steve


Re: sort with char’s

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

On Saturday, 12 August 2023 at 06:47:50 UTC, Joel wrote:

writeln(name[].each!(n => n.write)); // get 
"christensenyes" //, " <> ", name[].sort!"a>b".each!(n => 
n.write));


This writes each character individually, and then at the end 
writes the result of `each` with a newline.


In this case, `each` 
[docs](https://dlang.org/phobos/std_algorithm_iteration.html#each) say:


Returns:
Yes.each if the entire range was iterated, No.each in case of 
early stopping.


`Yes.each` is going to print as "yes".

-Steve


Re: Why is GC.collect not @safe?

2023-08-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/2/23 7:40 AM, Nick Treleaven wrote:
Presumably an allocation like `new T` (for a type with a @safe 
constructor) can be made anywhere a call to `GC.collect` can be made, 
which may trigger a collection. So why isn't `GC.collect` marked @safe?


It should be. Maybe historical reasons?

One possible (but wrong) reason is that destructors can be unsafe. But 
you are correct in that allocation can cause a collection.


-Steve


Re: HTTP Post Body Parameters

2023-08-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/1/23 7:57 PM, Vahid wrote:

Hi,

I want to submit a request to server with "x-www-form-urlencoded" 
header. This is the simplified version of my code:



     auto http = HTTP("https://myurl.com/api;);
     http.addRequestHeader("Content-Type", 
"application/x-www-form-urlencoded");

     http.addRequestHeader("Authorization", "SID:TOKEN");

     auto params = "Param1=one=two";
     http.setPostData(params, "application/x-www-form-urlencoded");

     http.onReceive = (ubyte[] response)
     {
     return cast(string) response;
     };


onReceive is a push from the library to you. Returning the response 
doesn't actually do anything. You need to store it somewhere.


e.g.

```d
ubyte[] msg;
http.onReceive = (ubyte[] response) {
msg ~= response;
return response.length; // tell the receiver how much data was read
};

http.perform(); // fills in msg
return msg;
```
from the std.net.curl docs about onReceive (which by the way, should 
return a ulong, I'm not sure how your cast to string even compiles):


The event handler that receives incoming data. Be sure to copy the 
incoming ubyte[] since it is not guaranteed to be valid after the 
callback returns.


-Steve


Re: Anyone help me with a stack dump?

2023-07-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/31/23 9:09 AM, Cecil Ward wrote:
The unitttests that I have just put in crash spectacularly with an 
access violation. I built the code with LDC for Aarch64 / OSX and I 
fired up lldb. I now have to learn lldb quick. (BTW Where can I get an 
x86 / linux build of lldb or similar ?)


This is the stack dump, and I could do with some help decoding parts of it



unittest_L1541 -> unittest on line 1541.

Probably something in there doing appending?

I myself have a hard time with lldb. I understand gdb a lot better.

-Steve


Re: AA vs __gshared

2023-07-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/28/23 11:15 AM, IchorDev wrote:

On Friday, 28 July 2023 at 11:15:31 UTC, Steven Schveighoffer wrote:
All `__gshared` does is give you storage that is accessible from all 
threads,


"All __gshared does is give you [a live bomb, ready to go off at any 
moment]"

!!


It seems like it's not __gshared at all, but misusing malloc with GC 
pointers.




On Friday, 28 July 2023 at 14:10:16 UTC, Kagamin wrote:
Your error is using allocating the object with malloc. Since gc 
doesn't see your AA, the AA is freed and you get UAF.


Friend, I think you nailed it. After adding this I haven't been able to 
reproduce the segfault again:

```d
this(long n){
 (){
     cache = new typeof(cache);
     assert(cache);
     import core.memory;
     core.memory.GC.addRoot(cast(void*)cache);
 }();
 // ...
```
It did always happen at random, so perhaps I haven't spent enough time 
testing it yet, but I've gone far longer without it segfaulting than 
ever before.


This is the wrong approach, it's the allocating call that should add the 
root (actually a range).


For instance, the mutex is not added, that might be collected. Or if you 
add more GC-pointing things into the class, that could be a problem.


What I'd do is:

```d
T alloc(T, A...)(auto ref A args){
enum classSize = __traits(classInstanceSize, T);
void* mem = core.stdc.stdlib.malloc(classSize);
assert(mem !is null, "Out of memory");
core.memory.GC.addRange(mem[0 .. classSize]);
scope(failure) {
   core.memory.GC.removeRange(mem[0 .. classSize]);
   core.stdc.stdlib.free(mem);
}
T inst = cast(T)mem;
inst.emplace(__traits(parameters));
return inst;
}
```

And of course, a `dealloc` that removes the range should also be added.

-Steve


Re: Syntax for Static Import of User Define Attributes

2023-07-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/28/23 8:10 AM, Vijay Nayar wrote:
However, this makes me wonder. Is there any reason why the `@` shouldn't 
recognize the dots in a fully-qualified-name on its own, without the 
need for parentheses?


It might be possible to expand the grammar. It seems very specific to 
UDAs, as it doesn't just throw out `Expression` or whatnot. It probably 
has to do with the spot that it's in (declaration). I'll defer to the 
compiler experts to decide what makes the most sense.


-Steve


Re: Syntax for Static Import of User Define Attributes

2023-07-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/28/23 4:15 AM, Vijay Nayar wrote:

On Thursday, 27 July 2023 at 21:24:44 UTC, Dennis wrote:

On Thursday, 27 July 2023 at 21:19:08 UTC, Vijay Nayar wrote:

Attempted Fix 2: Enclose the entire attribute name in parenthesis.
```
static import vibe.data.serialization;

class ChatCompletionFunctions {
  @(vibe.data.serialization.name)("name")
  ...
}
```


Try:

```D
@(vibe.data.serialization.name("name"))
```


This one causes a different error, because it invokes the 
template-argument syntax: https://dlang.org/spec/attribute.html#uda


I tried it and it worked for me. The template-argument syntax is normal. 
It's just a list of types or expressions (i.e. not a function argument list)


What is the error?

-Steve


Re: Designated initializers to function argument

2023-07-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/28/23 3:35 AM, IchorDev wrote:

On Tuesday, 11 July 2023 at 17:43:43 UTC, Steven Schveighoffer wrote:

On 7/11/23 11:22 AM, Ki Rill wrote:

On Tuesday, 11 July 2023 at 15:16:54 UTC, Ki Rill wrote:
apply(Appearance(color: BLACK, strokeWidth: 4)); // other fields are 
default initialized: strokeOpacity, fillOpacity,


Yes, I was going to reply that v 2.103 has added (stealthily) named 
parameters *as a partial implementation*. Included in this is struct 
initializers, and constructors and functions that are *not* templates.


If you are willing to use DMD 2.103 and above, you should be good.



N-no way?! The spec makes no mention of them, is it really safe to use 
them yet?


It isn't going away. I would wait a bit for libraries, because you don't 
want to force your users to require such a recent version of the 
compiler. Using it in an executable is fine.


-Steve


Re: AA vs __gshared

2023-07-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/28/23 4:39 AM, IchorDev wrote:


Issue is, this code I posted actually runs just fine, unlike the real code.
My actual code does this HIGHLY SUSPICIOUS thing when printing their 
length each time before using them:

```
766
766
765
766
767
768
768
768
768
768
768
768
768
768
768
768
768
768
768
128000
Error Program exited with code -11
(backtrace:)
#0  0x55670c46 in rt.aaA.Impl.findSlotLookup(ulong, scope 
const(void*), scope const(TypeInfo)) inout ()

#1  0x55661592 in _aaInX ()
```


My suspicion would be a race condition in your real code, and no race 
condition in this toy code. Second suspicion would be memory corruption 
(possibly caused by a race condition).


Therefore I must logically conclude that DRuntime's AAs are cursed! 
Unless this is a well-known issue or something...


AAs have worked forever. I've never had problems with them. Not saying 
there's not a bug here, maybe there is. But I would be surprised.


Thinking back, I've actually had them cause segfaults in non-threaded 
code, maybe `__gshared` was never the cause at all.


All `__gshared` does is give you storage that is accessible from all 
threads, but is not typed as `shared`. It doesn't change how the data is 
used.


-Steve


Re: Which D compiler is the most maintained and future-proof? [DMD GDC and LDC]

2023-07-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/24/23 9:30 AM, cc wrote:
On Monday, 24 July 2023 at 09:29:09 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

There isn't a huge concern with which one you use.

Its quite common to use dmd for development, and ldc for release for 
example.


They all share the same frontend, so they really only differ between 
them by their glue code to the relevant backend and some modules in 
druntime that are optional. Oh and inline assembly, although there is 
some compat code in ldc/gdc for dmd style.


If dmd dies, so does ldc/gdc basically. Each one sees active 
development although gdc only has one developer. Ldc keeps up with the 
dmd releases pretty well.


If DMD dies, the other two will live on. This is open source after all.



Is there any list of known significant "gotchas" with moving to LDC from 
DMD?  Any unexpected surprises to watch out for or be careful for?  I'm 
thinking of all the "features" of DMD that are now considered verboten 
by many users (e.g. compiling with -release, disabling of asserts or 
array bounds checking, etc). Known edge cases of compiler optimization 
causing different behavior between vendors?




DMD is the point of all D feature introductions, and so anything that 
works with LDC should work with DMD.


It's the other way around that might cause trouble, since there may be 
DMD features which haven't yet made it into LDC.


There are also subtle ways to consider things "broken" which might 
affect you if you care about that. Like for instance floating point 
handling is different, so you might not get exactly the same binary results.


-Steve


Re: Garbage Collectors

2023-07-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/19/23 10:46 AM, Johan wrote:
On Wednesday, 19 July 2023 at 11:27:14 UTC, Richard (Rikki) Andrew 
Cattermole wrote:


[...] you would have to do a new build of druntime/phobos special 
which isn't the easiest thing to do.


Side remark: LDC ships with the ldc-build-runtime tool which should help 
the user a lot in building druntime/phobos. (downloads the correct 
source belonging to the specific compiler version, and then builds the 
libraries with user-specified flags, compilers, etc.)


This is very cool to know, I wasn't aware!

-Steve



Re: Garbage Collectors

2023-07-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/19/23 3:24 AM, IchorDev wrote:
So, D’s default garbage collector is the one named “conservative” in 
DRuntime…
I see there’s also “manual” which doesn’t actually function as a GC, 
which is interesting.

Nothing says what ProtoGC is… so I guess it’s useless.
Has anyone ever published any custom GCs? A search through the dub 
package registry yielded nothing. How hard would it be to port (for 
instance) a Java GC to D’s interface?


To answer the question about ProtoGC, it is a stub GC which will create 
the appropriate GC (based on runtime flags) when the first function that 
requires actually using the GC is called. It is actually the default GC.


This was introduced to implement more pay-as-you-go runtime features. If 
you don't use the GC, no GC is created.


If I recall correctly, you must attempt to allocate using the GC for the 
ProtoGC to do its thing. Everything else is just simple stubs (e.g. 
ProtoGC.free does nothing, since it can never allocate memory)


-Steve


Re: Print debug data

2023-07-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/18/23 5:04 PM, Alain De Vos wrote:

?


use `stats` instead of `Stats`.

The `Stats` name is the type, whereas the `stats` method is the call 
that gets the stats.


It's kind of a terrible message, I wish it would change to something 
more informative.


-Steve


Re: How to free memory ater use of "new" to allocate it.

2023-07-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/16/23 11:58 PM, Alain De Vos wrote:

Maybe code above works when you enforce an Garbage-collection-run ?

Code below works fine. So you cannot use "new" but must use malloc?

```

import std.stdio:writefln;
import object: destroy;
import core.memory: GC;
import core.stdc.stdlib: malloc,free;


void dofun(){
    auto pa=cast(int *)malloc(1000*int.sizeof);
    writefln("%12x",pa);
    auto a=pa[0..1000];
    free(a.ptr);
}

int main(){
     dofun();
    auto pb=cast(int *)malloc(1000*int.sizeof);
    writefln("%12x",pb);
    auto b=pb[0..1000];
    free(b.ptr);
    return 0;

}

```


Notice how you didn't call `destroy(a)` there. If you did, then 
`free(a)` would be equivalent to `free(null)`, which would do nothing.


-Steve


Re: How to free memory ater use of "new" to allocate it.

2023-07-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/16/23 11:41 PM, Alain De Vos wrote:

The following program prints two different addresses.
Meaning the new allocates memory until the program dies.
So the means memory leak by default ?


```

import std.stdio:writefln;
import object: destroy;
import core.memory: GC;

void dofun(){
     auto a=new int[1000];
     writefln("%12x",);
     destroy(a);
     GC.free(a.ptr);
}

int main(){
     dofun();
     auto b=new int[1000];
     writefln("%12x",);
     return 0;
}

```



No, what I am trying to explain is that `destroy(a)` is literally 
equivalent to `a = null`.


If you then `free(a)` do you think it does anything?

-Steve


Re: How to free memory ater use of "new" to allocate it.

2023-07-16 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/16/23 2:41 PM, Alain De Vos wrote:

Is this ok ?
```
void main(){
 int[] i=new int[1];
     import object: destroy;
 destroy(i);
     import core.memory: GC;
 GC.free(GC.addrOf(cast(void *)(i.ptr)));
}
```


No, that won't work. Check out `i` value after you call `destroy` on it:

```d
destroy(i); // basically sets i = null
assert(i.ptr is null); // yep
GC.free(i.ptr); // basically free(null) which is a no-op
```

Also note that `destroy` is *shallow*. It does not dig into pointers or 
arrays. So even if your array was of elements with a destructor, 
destroying the array doesn't destroy the elements.


In this case, all you need to do is:

```d
GC.free(GC.addrOf(i.ptr));
```
You don't need the cast here. You shouldn't need the addrOf, but this is 
still open: https://issues.dlang.org/show_bug.cgi?id=13558


-Steve


Re: Issue De-referencing a Pointer to a Struct in an Array

2023-07-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/14/23 1:23 PM, Pen Hall wrote:


I think i figured out my issue...
The issue was that 'board' is a pointer, and all of the ways I tried to 
de-reference it, failed. I just tried the form 
`(*board)[number][symbol][letter]` which worked to de-reference it. 
`&(*board)[number][symbol][letter]`, of course, works to get a pointer 
to that spot in memory.


A nice abstraction available in D is a nested function.

e.g.:

```d
ref boardRef => *board;
// or with traditional syntax:
ref Tile[8][8][8] boardRef() { return *board; }
```

This should allow you to use `boardRef[number][symbol][i]`

-Steve


Re: Giant template - changing types everywhere

2023-07-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/14/23 12:40 PM, Christian Köstlin wrote:



Would Eponymous Templates 
(https://dlang.org/spec/template.html#implicit_template_properties) work 
with the wrapping template?


Only if all the functions are named the same as the template. With 
eponymous templates, you no longer get access to any of the members of 
the template aside from the eponymous member(s).


-Steve


Re: Giant template - changing types everywhere

2023-07-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/14/23 1:51 AM, Cecil Ward wrote:

On Friday, 14 July 2023 at 05:09:58 UTC, Cecil Ward wrote:

On Friday, 14 July 2023 at 05:05:27 UTC, Cecil Ward wrote:

On Friday, 14 July 2023 at 05:03:31 UTC, Cecil Ward wrote:


The way I can see it going is a giant template encompassing pretty 
much the whole file. Does that mean that the caller who calls my one 
public function does so by passing the type dchar or wchar ? And 
then we generate the strings from that. It might be rather more 
natural for the caller to pass one of the string types into the 
template. That’s where I get rather more confused, say caller calls


Transform(dstring)(dstring str)

or can they just do Transform( "str"d ) and it would work out that 
the type is immutable dchar[] ?


Perhaps I should just make up a small example file with two functions 
in it to see if I can get the syntax right?


If I wrap the whole thing with a template declaration of the xchar 
type, then can I get away with no changes to the individual function 
definitions?


I tried it, wrapped the whole thing in a template definition and it 
compiled, but then my test file which calls Transform( someDString ) 
failed to compile with errors saying it couldn’t find the definition of 
Transform in the other module, which is or was public. It’s as if it is 
no longer public because it’s now inside the template.


So templates don't automatically instantiate, you have to specify them. 
And then if your function is inside the template, to access it, you will 
need to do:


```d
GiantTemplate!dstring.Transform(str);
```

But this is not a usual way of creating API. Instead, you should 
template individual functions on the string type.


Depending on what you are doing, you can use:

```d
T Transform(T)(T val)
T[] Transform(T)(T[] val)
```

The first will cover cases where you have custom string types that 
aren't arrays, the second will just capture the array type, and ensures 
that the parameter/return is an array.


When you make template functions like this, a feature of D called 
Implicit Function Template Instantiation (IFTI) will automatically 
instantiate the template for you, so you don't have to specify the 
template parameters.


You just call `Transform(str)` and it works. With the wrapping template 
solution, this is not available -- you must explicitly instantiate the 
wrapper.


If you are having problems, it is nearly impossible to diagnose without 
some actual code to look at.


-Steve


Re: Giant template - changing types everywhere

2023-07-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/13/23 8:08 PM, Cecil Ward wrote:

What I really want to do though is provide one single templated function 
with the kind of characters / strings as a parameter. I want to have 
something like

T Transform( T )( T str)
called as
auto result = Transform!(dstring)( dstring str );


```d
T[] Transform(T)(T[] str)
```

Note that you don't have to specify the type when calling:

```d
Transform(someDstring); // infers dchar
```

I’m quite confused as to how to proceed. This is quite a large module ~ 
2k loc, and I don’t really want to go through and change every private 
function into a templated one. Should I just make the whole thing into a 
giant template containing many functions?


If you have more questions, please ask. Some examples of how making a 
template would be painful would be helpful.


-Steve


Re: Designated initializers to function argument

2023-07-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/11/23 11:22 AM, Ki Rill wrote:

On Tuesday, 11 July 2023 at 15:16:54 UTC, Ki Rill wrote:

```D

// or this
apply(Appearance(color: BLACK, strokeWidth: 4)); // other fields are 
default initialized: strokeOpacity, fillOpacity, etc...


```


Ok, this works with DMD v2.103, but does not work with an older version 
(I had ldc2 installed based on DMD v2.98).


Yes, I was going to reply that v 2.103 has added (stealthily) named 
parameters *as a partial implementation*. Included in this is struct 
initializers, and constructors and functions that are *not* templates.


If you are willing to use DMD 2.103 and above, you should be good.

-Steve


Re: Pre-expanding alloc cell(s) / reserving space for an associative array

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

On 7/10/23 8:44 AM, H. S. Teoh wrote:

On Mon, Jul 10, 2023 at 09:30:57AM +, IchorDev via Digitalmars-d-learn 
wrote:
[...]

 From the spec it sounds as though (but good luck testing for sure)
that if you have (for example) 6 big dummy key-value pairs in the AA
to begin with, then if you use `.clear` it "Removes all remaining keys
and values from [the] associative array. The array is not rehashed
after removal, __to allow for the existing storage to be reused.__"

[...]

This is not an accurate understanding of what actually happens.  The AA
implementation consists of a primary hashtable (an array), each slot of
which points to a list of buckets. Clearing the AA does not discard the
hashtable, but does dispose of the buckets, so adding new keys
afterwards will allocate new buckets.  So the buckets used by the dummy
key-value pairs do not get reused without a reallocation.


This used to be the case, but in the latest implementation, the AA uses
open addressing. That is, if a slot is full, it linearly searches the 
table for the next open slot. This cuts down significantly on cache 
misses, since the hash slot itself stores the hash, so the pointer only 
needs to be followed if the hash matches.


Fun historical fact, the original AA used a tree to store colliding 
elements, which means that all AA keys had to support both opEquals and 
opCmp.


BUT, you are right that the elements themselves are individual blocks of 
memory, and only the bucket array is reused.


If you want to see how the hash table works, without having to deal with 
all the typeinfo acrobatics that the actual builtin AA uses, you can 
look at my newaa library:


https://github.com/schveiguy/newaa

This is the exact implementation of the AA internals, but uses 
compile-time introspection instead of typeinfo.


-Steve


Re: Pre-expanding alloc cell(s) / reserving space for an associative array

2023-07-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/9/23 4:24 PM, Cecil Ward wrote:
Before I posted a question about avoiding unnecessary allocs/reallocs 
when adding entries to an array like so

     uint[ dstring ]  arr;

when I build it up from nothing with successive insertions.

The array is accessed by a key that is a dstring. I was told that I 
can’t use .reserve or the like on it? Is that correct? My memory fails 
me, powerful pain drugs.


Is there an alternate method I could use ? To be honest, the number of 
entries is likely to be extremely modest, so this is not a huge 
performance issue, six entries would be considered quite a lot. The 
string keys are probably not very very long. But I’m learning good 
habits for the day when I might have a bigger such database.


No there is no such `.reserve` call for associative arrays.

It might be possible to implement, but it's quite a bit different from a 
normal array reserve -- an associative array allocates all its elements 
as individual memory blocks, so there is no place to reserve things. You 
would have to add e.g. a free-list, that is reserved from the allocator 
itself.


-Steve


Re: Linker error, doing something wrong?

2023-07-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/9/23 10:01 AM, Dmitry Olshansky wrote:

Trying to compile the following:

https://github.com/DmitryOlshansky/photon/blob/master/tests/curl_download.d

with:
ldc2 curl_download.d -L-lcurl

get:

   "__D6photon12__ModuleInfoZ", referenced from:
   __D13curl_download12__ModuleInfoZ in curl_download.o
   "__D6photon5macos4core2goFDFZvZv", referenced from:
   __D13curl_download4mainFZ13spawnDownloadMFAyaQdZv in curl_download.o
   "__D6photon5macos4core9startloopFZv", referenced from:
   __Dmain in curl_download.o
   "__D6photon9runFibersFZv", referenced from:
   __Dmain in curl_download.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see 
invocation)

Error: /usr/bin/cc failed with status: 1

Am I missing something?


You need to link the library that contains photon.

-Steve


Re: Weird template instantiation speed?

2023-07-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/9/23 7:54 AM, IchorDev wrote:
While working on some new bindings, I've discovered that if `opAssign` 
in a struct template "`BindingTempl(T)`" has the return type 
"`BindingTempl!T` then it adds about 4 seconds to the compile time per 
instantiation of `BindingTempl`. The added compile time is much lower if 
a function other than `opAssign` returns `BindingTempl!T`. Is opAssign a 
particularly bad operator to overload in templates or something?


This is probably a bug somewhere, 4 seconds is too much. A reduced test 
case would be helpful.


But I wanted to note, inside a struct template, the template name (by 
itself) is equivalent to the current instantiation. So just returning 
`BindingTempl` would be equivalent, and might not trigger this problem.


See if that helps.

-Steve


  1   2   3   4   5   6   7   8   9   10   >