Re: Casting JSONValues arrays to native arrays ... ??? ...

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

On 9/24/21 12:58 AM, james.p.leblanc wrote:

On Thursday, 23 September 2021 at 20:32:36 UTC, james.p.leblanc wrote:

On Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc wrote:
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven Schveighoffer 
wrote:

On 9/23/21 2:20 PM, james.p.leblanc wrote:


```
Produces:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z5): question.main.MapResult!(__lambda2, 
JSONValue[]).MapResult, z5: [true, false, true]

z5: [true, false, true]



Sigh ... my suggested "minor edit" above produces a "map result" instead of
the desired native array ... here is the **fix** by appending ".array" 
at the

end (which is the suffix Steve originally offered).  The following gives
the desired **bool[]** result.

```d
import std.array;

    auto z5 = jj["ba"].array.map!(v => v.get!bool).array;
    writeln("typeid(z5): ", typeid(z5), ", z5: ", z5);
    writeln("z5: ", z5);
```


At first I thought that was allocating 2 arrays, but I didn't realize 
`JSONValue.array` was an actual member! When I saw your original code, I 
assumed the `.array` call was a call to `std.array.array`, and that 
`JSONValue` was somehow usable as a range.


So yes, that's what I should have written.

I admit I have not used `JSONValue`. That `array` accessor is quite a 
poor name due to the vast prevalence of using `std.array.array` to make 
an array out of some range. When using vibe.d's JSON type, I usually do 
`jsval[]` to access the array portion.


Note, you may want to consider whether you actually need a concrete 
array, as using the map result is pretty much equivalent, yet doesn't 
allocate anything.


-STeve


Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 2:20 PM, james.p.leblanc wrote:

Dear D-ers,

In attempting to cast JSONValues that hold arrays to "native" array types,
I have hit some issues.  Example code:

```d
import std.stdio;
import std.json;

void main(){

    JSONValue jj;
    jj["d"] = [ 1.234 ];  // a "dummy" double value
    jj["ba"] = [ true, false, true];  // "ba" boolean array


Note that this creates a JSONValue array which *copies* the values of 
the boolean array, converting them to JSONValue (which is what a 
JSONValue array stores).




    writeln("typeid(jj): ", typeid(jj), ", jj: ", jj );

    // various things that I thought might work, but do NOT

    auto z1 = cast(bool)   jj["ba"];   // attempt #1


A JSONValue cannot be cast to a boolean (it does not provide the 
appropriate opCast)



    auto z2 = cast(bool[]) jj["ba"];   // attempt #2
    auto z3 = cast(bool)   jj["ba"].array; // attempt #3


These try to cast something that is not an array to an array or vice 
versa. These are not supported unless the type itself has an `opCast` 
overload.



    auto z4 = cast(bool[]) jj["ba"].array; // attempt #4


Casting one array type to another is like pointing at the array that 
represents the original type *as if* it were of the new type. No 
translation is made, you are pointing at the same memory! The length is 
adjusted based on the size of the original array element and the size of 
the new one.


For instance:

```d
int[] arr = [1];
auto a2 = cast(ubyte[])arr;

assert(a2.length == 4);
assert(a2 == cast(ubyte[])([1, 0, 0, 0])); // assuming little endian
```



However, if I comment out the offending attempts (1, 2, and 3), then it
compiles, and can run ... but produces a result which I very much do NOT
understand:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z4): bool[], z4: [false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, false, 
true, false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, false, 
false, false, false, false, true, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, true, false, 
false, false, false, false, false, false]


This is an array of JSONValue, with each byte interpreted as if it were 
a bool.



H... is there a standard way to push these JSONValues into nice native
array types? (The real code is eventually going to be using traits and 
mixins

... but I do not think this should pose additional problems).


How you really do this:

```d
import std.algorithm : map;
auto z5 = jj["ba"] // get the JSONValue that is at the key "ba"
  .map!(v => v.get!bool) // map each value into a boolean
  .array // create an array out of the results;
assert z5 == [true, false, true];
```

(warning, untested)

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 1:44 PM, eugene wrote:

On Thursday, 23 September 2021 at 17:20:18 UTC, Steven Schveighoffer wrote:

So imagine the sequence:


With ease!


1. ctrl-c, signal handler triggers, shutting down the loop


Just a note: there is no 'signal handler' in the program.
SIGINT/SIGTERM are **blocked**, notifications (POLLIN) are received via 
epoll_wait().


Oh interesting! I didn't read the code closely enough.




2. main exits
3. GC finalizes all objects, including the Stopper and it's members


Probably, a destructor for Signal class should be added, in which

- close fd, obtained from signalfd()
- unblock the signal (thus default signal handler is back again)


Yes, I would recommend that. Always good for a destructor to clean up 
any non-GC resources that haven't already been cleaned up. That's 
actually what class destructors are for.




4. ctrl-c happens again, but you didn't unregister the signal handler, 
so it's run again, referencing the now-deleted object.


At this point we have default signal handler


5. segfault
It's theoretically a very very small window.


But even without destructor, no segfault will happen,
because **there is no signal handler**


So it gets written to the file descriptor instead? And nobody is there 
reading it, so it's just closed along with the process?


I've not done signals this way, it seems pretty clever and less prone to 
asynchronous issues.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 2:18 PM, eugene wrote:

On Thursday, 23 September 2021 at 17:16:23 UTC, Steven Schveighoffer wrote:

On 9/23/21 12:58 PM, eugene wrote:
On Thursday, 23 September 2021 at 15:56:16 UTC, Steven Schveighoffer 
wrote:

See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks 





"
This method references the obj parameter, making that object 
ineligible for garbage collection from the start of the routine to 
the point, in execution order, where this method is called. Code this 
method at the end, not the beginning, of the range of instructions 
where obj must be available.

"

**Code this method at the end...**

:)
it is the same as proposed by jfondren simple
writeln(stopper.sg0.number) in the end of main, right?


Same effect, but writeln actually executes code to write data to the 
console, whereas KeepAlive doesn't do anything.


```d
void keepAlive(Object o) {
}

void main(string[] args) {

     import core.memory : GC;

     auto Main = new Main();
     Main.run();

     auto stopper = new Stopper();
     stopper.run();

     writeln(" === Hello, world! === ");
     auto md = new MessageDispatcher();
     md.loop();

     keepAlive(Main);
     keepAlive(stopper);

     writeln(" === Goodbye, world! === ");
}
```
works ok with dmd, stopper is not collected.


With dmd -O -inline, there is a chance it will be collected. Inlining is 
key here.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 12:53 PM, eugene wrote:

On Thursday, 23 September 2021 at 15:53:37 UTC, Steven Schveighoffer wrote:
Technically, they should live past the end of main, because it's still 
possible to receive signals then.


No, as soon as an application get SIGTERM/SIGINT,
event queue is stopped and we do not need no
more notifications from OS (POLLIN/POLLOUT I mean).

Stopping event queue in this case is just
closing file descriptor obtained from epoll_create().
After this getting POLLIN from any fd (including signal fd) is
just impossible.




That's not what is triggering the segfault though. The segfault is 
triggered by the signal handler referencing the destroyed object.


So imagine the sequence:

1. ctrl-c, signal handler triggers, shutting down the loop
2. main exits
3. GC finalizes all objects, including the Stopper and it's members
4. ctrl-c happens again, but you didn't unregister the signal handler, 
so it's run again, referencing the now-deleted object.

5. segfault

It's theoretically a very very small window.

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 12:58 PM, eugene wrote:

On Thursday, 23 September 2021 at 15:56:16 UTC, Steven Schveighoffer wrote:

See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks 



"
This method references the obj parameter, making that object ineligible 
for garbage collection from the start of the routine to the point, in 
execution order, where this method is called. Code this method at the 
end, not the beginning, of the range of instructions where obj must be 
available.

"

**Code this method at the end...**

:)
it is the same as proposed by jfondren simple
writeln(stopper.sg0.number) in the end of main, right?


Same effect, but writeln actually executes code to write data to the 
console, whereas KeepAlive doesn't do anything.


Essentially, you get the side effect of keeping the object as live, 
without paying the penalty of inserting frivolous code.


All my efforts to achieve the same via a library were thwarted by at 
least LDC (whose optimizer is very good).


The only possible solution I can think of is to generate an opaque 
function that LDC cannot see into, in order to force it to avoid 
inlining, and have that function do nothing.


However, there's always Link-Time-Optmization...

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 9:18 AM, eugene wrote:

On Thursday, 23 September 2021 at 12:53:14 UTC, Steven Schveighoffer wrote:



We need to add a better way to do that (similar to C# KeepAlive).


Do you mean some function attribute?..



C# KeepAlive (and Go KeepAlive) are a mechanism to do exactly what you 
suggested -- use the object later.


However, they are recognized by the compiler as an intrinsic which 
generates no code or side effects, but is not subject to elimination by 
the optimizer.


See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 10:55 AM, eugene wrote:

On Thursday, 23 September 2021 at 14:31:34 UTC, jfondren wrote:
Nice. I thought of GC.addRoot several times but I was distracted by 
the general solution of using object lifetimes with it, so that a 
struct's destructor would call GC.removeRoot. For your case just 
pinning these and forgetting about them is the easiest way to do it.


Yes, these two must live until the end of main().
Moreover, in real (C) programs I (usually) do
not create state machines on the fly,
instead I keep them in pools, like RX/TX machines pools
in echo-server and in echo-client.



Technically, they should live past the end of main, because it's still 
possible to receive signals then.


But the chances of someone hitting ctrl-c in that window are quite small.

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 8:10 AM, eugene wrote:
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven Schveighoffer 
wrote:

I find it interesting how you blame yourself for C's idiosyncrasies


Me? Blaming *myself* for C 'idiosyncrasies'? :) Where?


"When my C program crashes, I'm 100% sure I made something stupid"

One might argue that C's approach to memory management is a contributor 
to people writing code that fails.



I would say C has far more pitfalls than D.


No doubt - and I've never said C is "better" than D.
I was going to try betterC subset
(say, try to implement dynamic arrays),
but did not have much free time yet.


Your assertion that programming in GC languages may be harder than 
manual memory languages is what I was addressing.


My point is that C has a lot more memory management pitfalls than D, not 
addressing any "better than" arguments.





Check out the undefined behaviors for C.


Nothing interesting...
Most of UB in C are just programmer's sloppiness.
C requires a programmer to be careful/punctual,
much more careful, than ... a python, for ex.


UB in C leaves traps for the programmer, similar to this trap you have 
found in the GC. Where code doesn't do what you are expecting it to do.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 3:27 AM, eugene wrote:
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven Schveighoffer 
wrote:
Your experience is not typical though (clearly, as many of us 
long-time D users had no idea why it was happening).


Oh, yeah - I have special trait of bumping against
various low probability things :)

But for sure if this turns you off, I can understand how it can be too 
frustrating to learn the new rules.


Show me these rules!


They are here: https://dlang.org/spec/interfaceToC.html#storage_allocation

With the caveat, of course, that the recommendation to "leave a pointer 
on the stack" is not as easy to follow as one might think with the 
optimizer fighting against that. We need to add a better way to do that 
(similar to C# KeepAlive). I made an 
[attempt](https://code.dlang.org/packages/keepalive), but I think it's 
not guaranteed to work, I've already found ways to prove it fails.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/22/21 11:47 AM, eugene wrote:
On Wednesday, 22 September 2021 at 12:26:53 UTC, Steven Schveighoffer 
wrote:

On 9/22/21 8:22 AM, eugene wrote:

And it follows that programming in GC-supporting languages
*may* be harder than in languages with manual memory
management, right?


I meant my this particular trouble...


In terms of any kind of memory management, whether it be ARC, manual, 
GC, or anything else, there will always be pitfalls. It's just that you 
have to get used to the pitfalls and how to avoid them.


I could see a person used to GC complaining that C requires you to free 
every pointer *exactly once*. I mean, how can that be acceptable? ;)



I do not want to understand how and what
compiler generates, I just want to
get working program without any oddities.


And for the most part, you do not. It's just when you travel outside the 
language, you must obey certain constraints. Those constraints are laid 
out, and unfortunately not exactly correct (we need to amend the 
spec/library for this), but given correct constraints, the rules are not 
super-difficult to follow.



Nevertheless, thank you again for your nice explanation!


You are welcome!

It's telling that I've been using D for 14 years and never had or seen 
this problem.


Bond. James Bond. :) 25 years of C coding.
Now, imaging a shock I was under when
I 'discovered' that swapping two lines of code
can magically fix my prog and make GC do
the right thing. :)


I'm right there with you (been writing code for about 25 years, maybe 
26, depending on when I switched majors to CS in college).


But realize that C has it's share of "shocks" as well, you are just more 
used to them (or maybe you have been lucky so far?)




Actually, D is a nice language per se
and I truly wish it to be as popular as java/python/etc.
But these GC ... mmm... 'features' may reduce
to zero any wish to learn D, that's about it.


Your experience is not typical though (clearly, as many of us long-time 
D users had no idea why it was happening). But for sure if this turns 
you off, I can understand how it can be too frustrating to learn the new 
rules. I personally would probably never write C code again if I can 
help it, despite having decades of experience in C/C++. I did recently 
have to port a C plugin library from PHP 5 to PHP 7, and it wasn't pleasant.




When my C program crashes, I'm 100% sure I made something stupid

- forget to initialize a pointer, easy to find and fix
- did some memory corruption (worse, but then electric fence is my best 
friend)


But if a crash is caused by 'optimization' + GC...
It looks like a programmer must keep some
implicit/unwritten rules in order to write correctly...



I find it interesting how you blame yourself for C's idiosyncrasies, but 
not for D's ;) I would say C has far more pitfalls than D. Check out the 
undefined behaviors for C.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/22/21 8:22 AM, eugene wrote:
On Wednesday, 22 September 2021 at 11:44:16 UTC, Steven Schveighoffer 
wrote:
Once it's on the stack, the GC can see it for the full run of `main`. 
This is why this case is different.


Note that Java is even more aggressive, and might *still* collect it, 
because it could legitimately set `stopper` to null after the last use 
to signify that it's no longer needed.


And it follows that programming in GC-supporting languages
*may* be harder than in languages with manual memory
management, right?



Only when interfacing with C ;) Which admittedly is a stated goal for D.

It's telling that I've been using D for 14 years and never had or seen 
this problem.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/21/21 4:17 PM, eugene wrote:

On Tuesday, 21 September 2021 at 19:42:48 UTC, jfondren wrote:

On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote:
There's nothing special about sg0 and sg1, except that they're part of 
Stopper. The Stopper in main() is collected before the end of main() 
because it's not used later in the function


Okay, but how could you explain this then

```d
void main(string[] args) {

     auto Main = new Main();
     Main.run();

     auto stopper = new Stopper();
     stopper.run();
```


Here is what is happening. The compiler keeps track of how long it needs 
to keep `stopper` around.


In assembly, the `new Stopper()` call is a function which returns in a 
register.


On the very next instruction, you are calling the function `stopper.run` 
where it needs the value of the register (either pushed into an argument 
register, or put on the call stack, depending on the ABI). Either way, 
this is the last time in the function the value `stopper` is needed. 
Therefore, it does not store it on the stack frame of `main`. This is an 
optimization, but one that is taken even without optimizations enabled 
in some compilers. It's called [dead store 
elimination](https://en.wikipedia.org/wiki/Dead_store).


Since the register is overwritten by subsequent function calls, there no 
longer exists a reference to `stopper`, and it gets collected (along 
with the members that are only referenced via `stopper`).




Now, change operation order in the main like this:

```d
void main(string[] args) {

     auto Main = new Main();
     auto stopper = new Stopper();

     Main.run();
     stopper.run();
```

```
d-lang/edsm-in-d-simple-example-2 $ ./test | grep STOPPER
'STOPPER' registered 5 (esrc.Signal)
'STOPPER' registered 6 (esrc.Signal)
'STOPPER @ INIT' got 'M0' from 'SELF'
'STOPPER' enabled 5 (esrc.Signal)
'STOPPER' enabled 6 (esrc.Signal)
```

Everything is Ok now, stopper is not collected soon after start.
So the question is how this innocent looking change
can affect GC behavior so much?...


In this case, at the point you call `Main.run`, `stopper` is only in a 
register. Yet, it's needed later, so the compiler has no choice but to 
put `stopper` on the stack so it has access to it to call `stopper.run`. 
 If it didn't, it's likely that `Main.run` will overwrite that register.


Once it's on the stack, the GC can see it for the full run of `main`. 
This is why this case is different.


Note that Java is even more aggressive, and might *still* collect it, 
because it could legitimately set `stopper` to null after the last use 
to signify that it's no longer needed. I don't anticipate D doing this 
though.


I recommend you read the blog post, it has details on how this is 
happening. How do you fix it? I have proposed a possible solution, but 
I'm not sure if it's completely sound, see 
[here](https://forum.dlang.org/post/sichju$2gth$1...@digitalmars.com). It 
may be that this works today, but a future more clever compiler can 
potentially see through this trick and still not store the pinned value.


I think the spec is wrong to say that just storing something as a local 
variable should solve the problem. We should follow the lead of other 
GC-supporting languages, and provide a mechanism to ensure a pointer is 
scannable by the GC through the entire scope.


-Steve


Re: Why dtor are not executed when removing a struct from associative arrays?

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

On 9/21/21 2:06 AM, Tejas wrote:

On Monday, 20 September 2021 at 18:13:53 UTC, Steven Schveighoffer wrote:

On 9/20/21 10:22 AM, Tejas wrote:
In case you still want to delete stuff deterministically despite what 
Steve said, I suggest you make your `struct` a reference and use 
`core.memory.__delete`(not recommended to use this carelessly, btw)


Do not call `__delete` here, use `destroy`. `__delete` will attempt to 
deallocate the block, which likely will fail since the key comes 
before the value, and GC.free on an interior pointer (I think) fails.


But if it succeeded, it would not be good. This leaves a dangling 
pointer inside the AA. Rehashing the AA likely would result in a 
memory corruption.


If you use destroy, the destructor will be called by the GC as well, 
but a struct should properly handle destroying the .init value.




It doesn't succeed when object is stack allocated, otherwise it works; 
that's why I suggested changing `S` to `S*`.


Oh! I missed that subtle change. I thought you were deleting a pointer 
to S that lives in a `S[int]`.


I still recommend against this because you can easily get a dangling 
pointer that way. Aside from that, if you are careful enough not to 
store a retrieved S* from the aa, you could do that. It will incur one 
extra allocation per element, which is not ideal.


Using destroy should be the most effective and safest mechanism.

-Steve


Re: Templates for instantiating derived class

2021-09-20 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/20/21 6:16 PM, rjkilpatrick wrote:
Essentially, I would like to write a template that calls the constructor 
of the parent class or the constructor of the inherited class, depending 
on its type.




...


Some kind of `return new this(...)` would be good, but that's not possible.
I think it has to be done with templates, but I'm not sure how to do this.

Any help would be greatly appreciated.


What you want is to change that operator into a virtual function. Yes, 
you still have to write the overrides, but you could if you want use a 
mixin. Adam's solution works, but only uses the static type.


```d
class Super {
private int _a;
this(){}
this(int a) {
_a = a;
}

Super performAdd(int rhs) const {
return new Super(_a + rhs);
}

alias opBinary(string op : "+") = performAdd;
}

class Derived : Super {
this(){}
this(int a) {
_a = a + 1;
}

override Derived performAdd(int rhs) {
return new Derived(_a + rhs);
}
}

void main() {
import std : writeln;

Super foo = new Super(1);
Super foo2 = foo + 1; // Works fine as calls `Super` constructor

Derived bar = new Derived(2);
Derived bar2 = bar + 1; // works now

Super b2 = bar;
Derived d2 = cast(Derived)(b2 + 1); // ok, *and* calls Derive's 
version of performAdd

assert(d2 !is null && d2._a == bar2._a);
}
```


Re: Why dtor are not executed when removing a struct from associative arrays?

2021-09-20 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/20/21 10:22 AM, Tejas wrote:
In case you still want to delete stuff deterministically despite what 
Steve said, I suggest you make your `struct` a reference and use 
`core.memory.__delete`(not recommended to use this carelessly, btw)


Do not call `__delete` here, use `destroy`. `__delete` will attempt to 
deallocate the block, which likely will fail since the key comes before 
the value, and GC.free on an interior pointer (I think) fails.


But if it succeeded, it would not be good. This leaves a dangling 
pointer inside the AA. Rehashing the AA likely would result in a memory 
corruption.


If you use destroy, the destructor will be called by the GC as well, but 
a struct should properly handle destroying the .init value.


-Steve


Re: Why dtor are not executed when removing a struct from associative arrays?

2021-09-20 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/20/21 8:23 AM, Learner wrote:

I was expecting something like going out of scope for that

```d
import std.stdio;

struct S
{
     ~this()
     {
     writeln("S is being destructed");
     }
}

void main()
{
 S[int] aa;
     aa[1] = S();
     aa.remove(1);
     writeln("Why no dtor call on remove?");
}
```
I was expecting S instance dtor called
S is being destructed


AA values are not destroyed on removal. For a simple reason -- someone 
might still be referencing it.


```d
struct S
{
   int x;
}
void main()
{
   S[int] aa;
   aa[1] = S(5);
   auto sptr = 1 in aa;
   sptr.x = 6;
   assert(aa[1].x == 6);
   aa.remove(1);
   assert(sptr.x == 6;
}
```

-Steve


Re: Extract base type of any array?

2021-09-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/19/21 12:20 AM, jfondren wrote:

On Sunday, 19 September 2021 at 03:58:41 UTC, Kirill wrote:
How can I get the base type of any 
(multidimensional/static/dynamic/associative) array?


Example:
```
void main() {
    int[][] intArr;
    double[4][] doubleArr;
    string[string][] strArr;

    intArr.example; // T = int
    doubleArr.example; // T = double
    strArr.example; // T = string
}

void example(T)(<...> data) {
    // extract the base of data (inside func's body or in <...>)
    // preferably, T must become data's base type
}
```


This almost works, but as `string` is an array type it needs some kind 
of rule to stop there:


```d
unittest {
     int[] intArr;
     double[4][] doubleArr;
     string[string][][] strArr;

     assert(is(BaseType!(typeof(intArr)) == int));
     assert(is(BaseType!(typeof(doubleArr)) == double));
     assert(is(BaseType!(typeof(strArr)) == immutable(char)));
}

template BaseType(T) {
     static if (__traits(isStaticArray, T))
     alias BaseType = BaseType!(typeof(T.init[0]));
     else static if (is(T == U[], U))
     alias BaseType = BaseType!U;
     else static if (is(T == V[K], K, V))
     alias BaseType = BaseType!V;
     else
     alias BaseType = T;
}
```

mix of BaseType!T from core.internal.array.equality and rank!T from 
Philippe Sigaud's D Templates Tutorial at 
https://github.com/PhilippeSigaud/D-templates-tutorial


You just need a case for it:

```d
static if(is(immutable(T) == immutable(string)))
   alias BaseType = T;
else ... // everything else
```

-Steve


Re: GC seems to crash my C-code function

2021-09-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/18/21 5:16 PM, frame wrote:

On Saturday, 18 September 2021 at 18:48:07 UTC, Steven Schveighoffer wrote:

Did you mean "long to char" cast? In that case, yes, you have to cast it.

Note, `out` is a keyword, it can't be used as a variable, but you 
probably already figured that out. But if `out` here is a `char *`, 
then yes, you need a cast there.




Yes, of course. `out(put)` is a `char[6]` here.



So here is why you need a cast:

First, the code is doing math on 2 pointers, which returns a 
`ptrdiff_t`, a.k.a. `long` in 64-bits.


Second, you are using mod 40, which is great, because D will recognize 
that the range of values must be within 40!


However, since it's signed, that's -40 to 40. Which doesn't fit in a 
`char` (which is unsigned).


D does not allow an implicit narrowing conversion. Since -40 to -1 won't 
fit into a char (dubious anyway for char to be an integer IMO), you need 
a cast.


So my recommendation is shoehorn it into ulong to take away the sign 
before the mod, or cast to char at the end. Is there any chance that `w` 
is less than `e`? if so, do NOT use the first option.


```d
// option 1
output[p++] = (ulong(w - e) + 3) % 40;
// option 2
output[p++] = cast(char)(((w - e) + 3) % 40);
```

Remember also, `char` is C's only way to say "byte". So this may just be 
data, and not unicode data. You may want to consider using `ubyte` in 
your translation instead of `char`. But wait until your code is 
compiling and working as it did in C.


-Steve


Re: GC seems to crash my C-code function

2021-09-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/18/21 5:20 PM, frame wrote:

On Saturday, 18 September 2021 at 21:16:13 UTC, frame wrote:
On Saturday, 18 September 2021 at 18:48:07 UTC, Steven Schveighoffer 
wrote:
Are you defining the prototype for strchr yourself instead of 
importing it from core.stdc.string?


Not really :D but without cast it complains:
```
Error: cannot implicitly convert expression strchr(e, cast(int)c) of 
type const(char)* to char*

```


But I guess it's because it tries to assign to a `char*` therefore 
inout() doesn't work.





Well, the variable you are assigning it to should be a `const char *` if 
the source variable is a `const char *`.


Possibly, the C code didn't mark it as `const char *`, because I'm 
pretty sure C has `strchr` being:


`char * strchr(const char *, int)`

Because, you know, const doesn't matter in C ;)

If that doesn't work, then you *may* need to start allocating. But I'd 
try that first.


-Steve


Re: GC seems to crash my C-code function

2021-09-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/18/21 12:52 PM, frame wrote:
There were also parts where the pointer is used in calculations - which 
is accepted by the compiler - it just complains about implicitly `long` 
to `char*` cast:

```
// const char *e
// char *w
out[p++] = ((w - e) + 3) % 40;
```


Did you mean "long to char" cast? In that case, yes, you have to cast it.

Note, `out` is a keyword, it can't be used as a variable, but you 
probably already figured that out. But if `out` here is a `char *`, then 
yes, you need a cast there.


-Steve


Re: GC seems to crash my C-code function

2021-09-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/18/21 12:52 PM, frame wrote:

On Saturday, 18 September 2021 at 11:47:52 UTC, Steven Schveighoffer wrote:


Have you tried:

```d
const(char)* s2 = "...";
```

This will work because string literals are zero terminated and 
implicitly castable to `immutable(char)*`, which will also implicitly 
cast to `const(char)*`.


That should allow s2 to be reassigned but not modify the data. IIRC, 
string literal data even in C is put into a read-only section by many 
compilers, so the code shouldn't be changing it.

...


The first rule of porting -- just translate, don't change anything. I 
would try to do exactly what C does without using the GC at all. 
Continue to use malloc/free. If you have issues with type 
representation, you may need to adjust for that.


This is what I try to achieve - not to change much.
But I see there is a mistake by me, s2 __is__ const in the original 
C-code too.


Unfortunately, with `const(char)*`, `strchr()` did complain and then I 
would have to cast it to `char*` - so I didn't used it in first place 
because I really thought `.dup` wouldn't allocate here.


`dup` definitely allocates. But when I look at the [dlang docs for 
strchr](https://dlang.org/phobos/core_stdc_string.html#.strchr), it 
properly adds the `inout` type modifier which should correct that 
problem. Are you defining the prototype for `strchr` yourself instead of 
importing it from `core.stdc.string`?




There were also parts where the pointer is used in calculations - which 
is accepted by the compiler - it just complains about implicitly `long` 
to `char*` cast:

```
// const char *e
// char *w
out[p++] = ((w - e) + 3) % 40;
```

Why doesn't the compiler complain about
`char* - const(char)*`?
`long` doesn't implicitly cast to `char *`. But of course, subtracting 
two pointers works for the same base type.


Note that `long` in C is *not the same* as `long` in D.

You should take a look at 
https://dlang.org/spec/interfaceToC.html#data_type_compat


-Steve


Re: What is the meaning of @future ?

2021-09-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/18/21 7:49 AM, Steven Schveighoffer wrote:

add buys


"ad buys" of course :P

-Steve


Re: GC seems to crash my C-code function

2021-09-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/18/21 5:40 AM, frame wrote:

On Friday, 17 September 2021 at 14:29:23 UTC, Steven Schveighoffer wrote:

Looking at that signature, it does not appear that it uses 
zero-termination at all, as it takes a length. So using `dup` and 
therefore the gc is totally unnecessary.


I'm assuming that string is the barcode argument?


No, the string appears inside the C-function. I'm calling the function 
with .ptr and the .length property as it expects.


Oh wow, I totally misunderstood what you are doing. I thought you were 
*calling* that function, but you are *reimplementing* that code in D.


Have you tried:

```d
const(char)* s2 = "...";
```

This will work because string literals are zero terminated and 
implicitly castable to `immutable(char)*`, which will also implicitly 
cast to `const(char)*`.


That should allow s2 to be reassigned but not modify the data. IIRC, 
string literal data even in C is put into a read-only section by many 
compilers, so the code shouldn't be changing it.


Now that I understand what you are doing, it becomes clear that this 
isn't a situation of C code being called. Or are you calling other parts 
of the C library with that translated function?


The first rule of porting -- just translate, don't change anything. I 
would try to do exactly what C does without using the GC at all. 
Continue to use malloc/free. If you have issues with type 
representation, you may need to adjust for that.


-Steve


Re: What is the meaning of @future ?

2021-09-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/18/21 4:02 AM, Dylan Graham wrote:

On Friday, 17 September 2021 at 14:37:29 UTC, Meta wrote:

On Friday, 17 September 2021 at 10:31:34 UTC, bauss wrote:

On Thursday, 16 September 2021 at 20:53:34 UTC, Elmar wrote:

[...]


It's just another "useless" attribute that the language has added 
before fixing any of the real problems :)


Basically it reserves a symbol for the future.

It's similar to creating ex. an empty function that throws an error 
or something like "Not implemented"


While I understand why it was added and what purpose it serves then I 
fail to see why that  was prioritized over actual issues.


It's solving an almost non-existing issue.


I think the main reason it was added is because Sociomantic asked for 
it, but they are of course not around anymore.


Off topic: what happened to them, out of curiosity?


Google changed the rules for add buys. Which either killed their 
business model, or made them far less competitive than they were originally.


-Steve


Re: GC seems to crash my C-code function

2021-09-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/17/21 2:27 AM, frame wrote:

On Thursday, 16 September 2021 at 18:02:44 UTC, Steven Schveighoffer wrote:

Are you sure? Be very pedantic about what C functions do with the data 
you send it. Sometimes they store it somewhere to use later. Sometimes 
they expect it to be allocated by the C heap, etc.


Without seeing how you use it, I can't tell you if it's wrong or not.


If you want to have a look the original C-library is here
https://github.com/rdoeffinger/iec16022

I'm only using the encoder function iec16022ecc200f.


Looking at that signature, it does not appear that it uses 
zero-termination at all, as it takes a length. So using `dup` and 
therefore the gc is totally unnecessary.


I'm assuming that string is the barcode argument?

What does your call look like?





If it's a literal, you don't need to toStringz (which also allocates). 
All string literals are zero-terminated (and actually implicitly 
castable to `immutable char *`).




Thanks, I'm just careful with casting.
Does it really allocate from a literal if it's used on the stack only? 
Is `-vgc` switch reliable?


The `-vgc` switch appears to only identify allocations that the compiler 
invokes via hooks, not ones that other functions invoke (or ones that 
are direct calls into the GC).


In other words, it helps you find your direct allocations using the 
compiler, not ones that are buried in already-compiled code.


Try this with `-vgc`, and it reports nothing:

```d
import core.memory;
void main()
{
   auto x = GC.malloc(10);
}
```

This makes sense, as it may not have the function code to analyze, and 
it also cannot infer GC allocation from a lack of @nogc (a non-@nogc 
function *may* allocate, but does not *necessarily* allocate). It also 
would be quite useless to see some function buried inside druntime that 
allocates, not knowing what the call stack was.


The docs for `-vgc` should really be updated to clarify. It currently 
just says "List all gc allocations including hidden ones".


-Steve


Re: GC seems to crash my C-code function

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

On 9/16/21 1:08 PM, frame wrote:

On Thursday, 16 September 2021 at 15:34:25 UTC, Steven Schveighoffer wrote:

`dup` is a GC allocation. Are you using that in your C code? the GC 
might be collecting that string.


The compiler doesn't show that lines with -vgc. Maybe it knows that it 
is only stack allocated?


Technically, the GC could collect that data if it wants - it's not 
longer used after the function returns. At least I control that the GC 
cannot collect it till my data is processed, so there should be no problem.


Are you sure? Be very pedantic about what C functions do with the data 
you send it. Sometimes they store it somewhere to use later. Sometimes 
they expect it to be allocated by the C heap, etc.


Without seeing how you use it, I can't tell you if it's wrong or not.



I guess the C-methods did corrupt the memory which the compiler has 
reserved for that function data statically and then the GC collect marks 
it as free or some other UB.




You are better off to cast away the immutable (as long as you are 100% 
sure the C code isn't writing to it), as the string literal will not 
be collected.




Yes, I changed it to stringz and a cast and the problem is gone so far. 
All char* are read only in the function or passed to stdlib functions 
that should not modify it.





If it's a literal, you don't need to toStringz (which also allocates). 
All string literals are zero-terminated (and actually implicitly 
castable to `immutable char *`).


-Steve


Re: GC seems to crash my C-code function

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

On 9/16/21 6:28 AM, frame wrote:
I have C-code translated in D that acts sometimes incorrect if the GC 
has made some collect. I would like to know why.


- Code runs correct if the GC collections are off
- There are no allocations within the C-translated-code except `throw 
new` (but they are not called)


...


I didn't want to change the code much so I have some piece like that:
```d
// const char *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_";
char* s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_".dup.ptr;
```
Could this cause the issue? But the pointer is not used outside the 
function where it's created.


`dup` is a GC allocation. Are you using that in your C code? the GC 
might be collecting that string.


You are better off to cast away the immutable (as long as you are 100% 
sure the C code isn't writing to it), as the string literal will not be 
collected.


-Steve


Re: uint overflow behaviour

2021-09-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On Wednesday, 15 September 2021 at 10:08:13 UTC, DLearner wrote:
Please confirm that if the addition of two uint variables 
produces a result larger than can be held in a uint:
1.  This is a D-legal operation (however inadvisable!), with 
the D-defined result of wraparound;


Definition under point 7 here : 
https://dlang.org/spec/expression.html#add_expressions


And I wouldn’t say inadvisable. It’s defined and if you have a 
good reason to allow that, then you can do that.


2.  Emphasing 1. above: the result is not undefined, or an 
error (by the rules of D), or simply implementation-dependant 
(whether by compiler or chip).


Yes

-Steve




Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/14/21 2:05 PM, eugene wrote:

On Tuesday, 14 September 2021 at 17:02:32 UTC, jfondren wrote:

It doesn't seem like communication between us is possible


and you are wrong, as usual ,)


in the "a five-pound phone won't sell" way.


I am not a 'selling boy'


My suggestion remains: try troubleshooting by making your program @safe.


Please, take that clever bot away.


People are trying to help you here. With that attitude, you are likely 
to stop getting help.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/14/21 10:56 AM, jfondren wrote:

On Tuesday, 14 September 2021 at 14:40:55 UTC, eugene wrote:
On Tuesday, 14 September 2021 at 12:09:03 UTC, Steven Schveighoffer 
wrote:

This project is too big and complex


Really, "too big and complex"?
It's as simple as a tabouret :)
It's just a toy/hobby 'project'.


A 5-pound phone isn't "too heavy" for an adult to carry but it won't 
sell well. It's not just about capabilities but what efforts people are 
willing to expend.


I would troubleshoot your issue by gradually making it @safe and 
thinking about exceptions. One exception I didn't think about earlier 
was the 'misaligned pointer' one that I said I suppressed just to find 
the next @safe complaint:


https://dlang.org/spec/garbage.html says:


Do not misalign pointers if those pointers may point into the GC heap,


So even if the lifetimes of your EventSource structs are fixed, the GC 
can reap the object they're pointing to. You could fix this by having a 
128-bit struct and passing C an index into it, so to speak.


I don't think this is the problem.

The misaligned pointers are only happening within the stack frame, along 
with references to the objects stored also in another parameter. So they 
should not cause problems with the GC.


The storage of the references inside other objects is not misaligned.

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/14/21 8:42 AM, eugene wrote:

On Tuesday, 14 September 2021 at 12:09:03 UTC, Steven Schveighoffer wrote:


I still recommend pinning the object when adding the epoll event and 
seeing if that helps.


I understand your idea, but even if this will help, the question
remains - why that particular object is so special for GC.



Philosophically, it places the responsibility of making sure the object 
is valid while using it on the thing that chooses to store it outside 
the GC's view.


Looking at your examples, you are having to store these object 
references elsewhere, surrounding seemingly innocuous and normal D usage 
of objects. You have put the burden on the caller to make sure the 
implementation details are sound.


But I agree that a superficial reading of your code seems like it ought 
to not be collected, and that problem is also worth figuring out. I have 
high confidence that it's probably not a design flaw in the GC, but 
rather some misunderstanding of GC-allocated lifetimes in your code. But 
that doesn't mean it's not actually a bug somewhere in D.


-Steve


Re: Recommendations on parsing XML via an InputRange

2021-09-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/13/21 10:43 PM, Chris Piker wrote:

Hi D

I just finished a ~1K line project using `dxml` as the XML reader for my 
data streams.  It works well in my test examples using memory mapped 
files, but like an impulse shopper I didn't notice that dxml requires 
`ForwardRange` objects.  That's unfortunate, because my next enhancement 
was to start parsing streams as they come in from stdin. (doh!)


So I've learned my lesson and will RTFM closer next time, but now I'm 
casting about for a solution.  Two ideas, either:


1. Find a different StAX-ish parser that works with `InputRange` (and 
buffers internally a bit if needed), or


2. Find a way to represent standard input as a ForwardRange without 
saving the whole stream in memory. (iopipe?)


Iopipe is no better than an input range unless you plan to read the 
whole stream into a buffer.


A forward range is required because dxml uses saved ranges to refer to 
previous data. This requires the whole thing to be stored in memory.


I've thought of building an xml parser on top of iopipe, and I probably 
will some day (maybe a port of dxml). The iopipejson library does not 
require the whole thing to be in memory, and has some facilities to pin 
parsed data to jump back. I imagine something like that is doable for 
xml, but probably just storing current element ancestry while parsing 
(probably off to the side in another stack-like thing).


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/14/21 7:31 AM, eugene wrote:

On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote:
Then after pressing ^C (SIGINT) the program gets SIGSEGV, since 
references to sg0 and sg1 are no longer valid (they are "sitting" in 
epoll_event structure).


... forget to mention, crashes here:

```d
     bool wait() {

     const int maxEvents = 8;
     EpollEvent[maxEvents] events;

     if (done)
     return false;

     int n = epoll_wait(id, events.ptr, maxEvents, -1);
     if (-1 == n)
     return false;

     foreach (k; 0 .. n) {
     EventSource s = events[k].es;
     ulong ecode = s.eventCode(events[k].event_mask); // < 
SIGSEGV

```

sg0/sg1 are destroyed, so s points to wrong location.




Note that s likely still points at a valid memory address. However, when 
an object is destroyed, its vtable is nulled out (precisely to cause a 
segfault if you try to use an already-freed object). There is also the 
possibility the memory block has been reallocated to something else, and 
that is causing the segfault. But if the segfault is consistent, most 
likely it's the former problem.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/14/21 1:49 AM, Tejas wrote:

On Monday, 13 September 2021 at 18:42:47 UTC, Steven Schveighoffer wrote:

On 9/13/21 1:54 PM, eugene wrote:

[...]


The GC only scans things that it knows about.

Inside your EventQueue you have this code:

[...]


Umm is it okay that he declared variables `init` and `idle` of type 
`Stage` inside the constructor? Maybe that has something to do with 
this? Also, calling a variable `init` could be problematic since the 
compiler assigns a property of the same name to every single type?


Declaring a member/field named `init` is likely a bad idea, but this is 
not a member, it's just a variable. That's fine. `idle` doesn't mean 
anything special to D.


This project is too big and complex for me to diagnose by just reading, 
it would take some effort, and I don't have the time, sorry. Though as I 
have learned helping C converts before, most of the time things like 
this have to do with forgetting to store a GC reference somewhere. It 
can be subtle too...


I still recommend pinning the object when adding the epoll event and 
seeing if that helps.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/13/21 1:54 PM, eugene wrote:

On Monday, 13 September 2021 at 17:40:41 UTC, user1234 wrote:
The problems seems to lies in `newSignal()` which "would" not allocate 
using the GC.


     final Signal newSignal(int signum) {
     Signal sg = new Signal(signum);
     sg.owner = this;
     sg.number = sg_number++;
     sg.register();
     return sg;
     }

full src is here
http://zed.karelia.ru/0/e/edsm-in-d-2021-09-10.tar.gz



The GC only scans things that it knows about.

Inside your EventQueue you have this code:

```d
void registerEventSource(EventSource es) {
auto e = EpollEvent(0, es);
int r = epoll_ctl(id, EPOLL_CTL_ADD, es.id, );
assert(r == 0, "epoll_ctl(ADD) failed");
}

EventQueue opOpAssign(string op)(EventSource es)
if (("+" == op) || ("~" == op)) {
registerEventSource(es);
return this;
}

void deregisterEventSource(EventSource es) {
auto e = EpollEvent(0, es);
int r = epoll_ctl(id, EPOLL_CTL_DEL, es.id, );
assert(r == 0, "epoll_ctl(DEL) failed");
}

EventQueue opOpAssign(string op)(EventSource es)
if ("-" == op) {
deregisterEventSource(es);
return this;
}
```

And you are registering your signals using the `+=` operator.

What is happening here, is, `epoll_ctl` is adding your event source to a 
*C allocated* structure (namely the epoll struct, allocated by 
`epoll_create1`, and possibly even managed by the OS). The GC does not 
have access to this struct, so if that's the only reference to them, 
they will get cleaned up by the GC.


Now, with your stopper code that you showed, it looks like you are 
storing the reference to stopper right on the main stack frame. This 
*should* prevent those from being destroyed, since Stopper has a 
reference to both signals.


But I would recommend using `core.memory.GC.addRoot` on your EventSource 
when registering it with epoll, and using `core.memory.GC.removeRoot` 
when unregistering. That will ensure they do not get cleaned up before 
being unregistered. If this doesn't fix the problem, perhaps there is 
some other issue happening.


-Steve


Re: Which operators cannot be overloaded and why not?

2021-09-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/13/21 10:47 AM, user1234 wrote:

On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote:

what else ?


when you have

```d
alias AA1 = int[int];
alias AA2 = AA1[int];
```

then you can write

```d
AA2 aa;
aa[0] = [0 : 0];
aa[0][0] = 0;
```

The `[0][0]` cannot be expressed using operator overloads (and a custom 
map type that implements opIndexAssign).But this case is rather due to 
the fact that druntime seems to do something a bit unusal here 
(according to an old discussion that happend once on irc).




This is because the compiler calls a different hook depending on the 
usage of the expression `aa[0]`. Which one it calls is not consistent.


There isn't an analog for indexing overloads.

A further example:

```d
int[int] aa;
aa[0]++; // ok
void foo(ref int x) {x++;}
foo(aa[1]); // range violation
```

-Steve


Re: Ali's Book - Programming in D

2021-09-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/10/21 10:21 AM, Ali Çehreli wrote:
I want to thank Steven Schveighoffer here once more for his help with 
the book. I later realized that his name should have much more 
prominence. I can't understand how my older self did not realize this 
fact when the book was being finalized.


Your memory may be quite faulty! I think I did review quite a bit of it, 
but I think I didn't finish reviewing everything (it is a big book).


But thank you!

-Steve


Re: GDC - program runs in one thread, DMD - in 4 threads, why?

2021-09-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/10/21 7:47 AM, eugene wrote:

On Friday, 10 September 2021 at 11:09:10 UTC, bauss wrote:
--DRT-gcopt=parallel:2 on the command line. A value of 0 disables 
parallel marking completely.


but it does not:

make -f Makefile-dmd
dmd --DRT-gcopt=parallel:0 engine/*.d common-sm/*.d server-sm/*.d pool.d 
echo_server.d -ofecho-server
dmd --DRT-gcopt=parallel:0 engine/*.d common-sm/*.d client-sm/*.d pool.d 
echo_client.d -ofecho-client


ps xH | grep [e]cho
  5460 pts/14   Sl+    0:00 ./echo-server
  5460 pts/14   Sl+    0:00 ./echo-server
  5460 pts/14   Sl+    0:00 ./echo-server
  5460 pts/14   Sl+    0:00 ./echo-server
  5466 pts/15   Sl+    0:00 ./echo-client
  5466 pts/15   Sl+    0:00 ./echo-client
  5466 pts/15   Sl+    0:00 ./echo-client
  5466 pts/15   Sl+    0:00 ./echo-client





`--DRT...` is a d runtime switch, which is processed while running your 
program, not by the compiler.


Try `./echo-client --DRT-gcopt=parallel:0`

There is also a way to add this to your program so it's not needed on 
the command line.


-Steve


Re: Ali's Book - Programming in D

2021-09-10 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/10/21 6:46 AM, Ron Tarrant wrote:
I guess this is mainly a question for Ali, but if anyone else knows the 
answer, please jump in...


If I were to buy a paperback copy of "Programming in D: Tutorial & 
Reference" from Amazon (this link: 
https://www.amazon.ca/Programming-Tutorial-Reference-Ali-Cehreli/dp/1515074609/ref=sr_1_1?dchild=1=programming+in+d%3A+tutorial+and+reference=1631270580=8-1) 
would I be getting the 2021 edition or an earlier one?


If I can't get the latest edition from Amazon, is there a place where I 
can get it?


Thanks.


Ali's book is generally "print-on-demand".

But I don't know the details of how often it gets re-upped on those sites.

I'd suggest you wait for Ali to wake up (he's on west coast of the US), 
and he likely will respond ;)


-Steve


Re: Is std.variant useful for types only known at run time?

2021-09-08 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/8/21 5:55 AM, Chris Piker wrote:

On Wednesday, 8 September 2021 at 08:39:53 UTC, jfondren wrote:

so I'd look at a std.sumtype of them first:


Wow, this forum is like a CS department with infinite office hours!

Interesting.  I presume that the big win for using std.sumtype over a 
class set is value semantics instead of reference semantics?


So out of curiosity, say each structure implemented a function to 
provide the desired broken-down-time, would the following "virtual 
function" style call work?


```d
import std.sumtype;
struct BDTime { int y, int m, int d, int h, int m, double s };

struct ISO8601 { BDTime bdTime(){ ... }  }
struct FloatEpoch { BDTime bdTime(){ ... } }
struct DoubleEpoch { BDTime bdTime(){ ... } }
struct LongEpoch { BDTime bdTime(){ ... }  }
alias Time = SumType!(ISO8601, FloatEpoch, DoubleEpoch, LongEpoch);

void main() {
     import std.stdio : writeln;
     import std.format : format;

     Time e = ISO8601();
     BDTime = e.bdTime();
}
```
or would I need to use `match!` to get the right structure type and then 
generate the internal time representation?





Just as an aside, 
[taggedalgebraic](https://code.dlang.org/packages/taggedalgebraic) does 
this for you.


-Steve


Re: Forum posting question ... how post a thread question with color syntax highlighting ??

2021-09-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/6/21 10:13 AM, Mike Parker wrote:

On Monday, 6 September 2021 at 13:23:21 UTC, Steven Schveighoffer wrote:



I will note though, that some people use the mechanism for links that 
puts the link at the bottom of the post, and this can be annoying when 
you reply, if you don't include the link definition, it doesn't render 
correctly.




Now that's interesting. I had assumed it would be less annoying than 
having them inline. Especially since people had already adopted a 
similar convention before we got Markdown support. I gave up on 
Thuderbird and went full-on with the web interface a couple of years 
ago, so I've had no view of the experience post-Markdown.





Yeah the convention isn't terrible, but it looks weirder for sure when 
the link is missing.


E.g. look at this post: 
https://forum.dlang.org/post/miahenxocgxpvasqg...@forum.dlang.org


and then a reply: 
https://forum.dlang.org/post/jreujgbixqadnwjsi...@forum.dlang.org


-Steve


Re: Forum posting question ... how post a thread question with color syntax highlighting ??

2021-09-06 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/5/21 9:18 PM, Ali Çehreli wrote:

On 9/5/21 4:24 PM, someone wrote:
 >
 > For example; IIRC Ali's posts are always no-markdown.
 >

That's because I've been using Thunderbird for mail and news for a long 
time now and unfortunately it is impossible to convince Thunderbird to 
add the necessary header field. (Vladimir has a recommendation where I 
can run a simply local server that augments Thunderbird's headers but I 
haven't tried it yet.)


I should go back to using Emacs for news. I am pretty sure it will be 
configurable.


Ali



This is *exactly* how I do it. Though I have started creating an 
iopipe-based clone cause I wanted to see if I could do it. Unfortunately 
std.io is not mature enough.


I plan to have a dub project so you can just `dub run 
thunderbirdmarkdown` and now you have a solution.


And to answer someone's question, I think everyone is fine with 
markdown, they just don't always have the capability.


I will note though, that some people use the mechanism for links that 
puts the link at the bottom of the post, and this can be annoying when 
you reply, if you don't include the link definition, it doesn't render 
correctly.


-Steve


Re: Forum posting question ... how post a thread question with color syntax highlighting ??

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

On 9/5/21 2:07 PM, james.p.leblanc wrote:


But, my eyes had been looking for the beautiful green and blue
text as an example ...  So, I completely missed the fact
that the "highlight syntax" in the box was exactly what
I was looking for.


Actually, it may not be a bad idea to make that example markdown more 
colorful by adding some keywords and comments. Maybe instead of


```d
writeln("D is great!");
```

it could be:

```d
// should be highlighted!
auto str = "D is great!";
```

-Steve


Re: Forum posting question ... how post a thread question with color syntax highlighting ??

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

On 9/5/21 1:48 PM, james.p.leblanc wrote:

Dear All,

I have noticed that quite a few posts and responses on this
forum include d snippets made with **nicely colored syntax highlighting.**
(I do not mean just the bold markdown text.)

This increases post clarity significantly.

How is this being done?  (I hope that this is not considered off
topic.  My goal would be able to make such posts myself.  But also,
if more post in this manner, it may help many.)


The markdown link in the forum UI should tell you how it works.

In case you can't find it, the info is 
[here](https://forum.dlang.org/help#markdown)


-Steve



Re: Phobos Unittest

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

On 9/4/21 4:05 PM, Per Nordlöw wrote:

On Saturday, 4 September 2021 at 13:12:49 UTC, Steven Schveighoffer wrote:
Note that lexing and parsing is extremely quick, and I wouldn't focus 
on trying to trim this out, you won't get much performance out of that.


-Steve


For the record, a D file containing only `import std;` type checks via

```sh
time dmd import_std.d -o-
```

in 0.20s whereas

```sh
time dmd import_std.d -o-
```

in 0.45s on my ThreadRipper.


I doubt that's because of the parsing. I've [gone 
down](https://github.com/schveiguy/dmd/tree/debugunitteststuff) these 
kinds of rabbit holes. It's one of the reasons I tried to remove ALL 
version(unittest) blocks from phobos that import other modules. But you 
just can't remove them all. And any unittests inside templates are going 
to compile and get included, even if you don't instantiate anything. I 
also discovered that CTFE initializers run, even if you don't use the 
imported symbol, and even if you don't need type inference. Can't 
remember if that got fixed.


I think you would find you could probably attribute the 0.25s there to a 
few modules that do things when unittests are turned on.


According to 
https://github.com/dlang/dmd/blob/1ae5fee06ddd0599fb187595f8b0cebf8c840ebd/src/dmd/parse.d#L642-L683, 
if unittests aren't turned on, indeed the parser simplifies its parsing 
of the unittest. It skips over the unittest block, and doesn't allocate 
any AST nodes for it. But that difference I don't think is going to be 
the cause for a significant slowdown.


One can construct a test to check the parsing:

1. Generate a huge source file with 10,000 (or maybe more?) non-trivial 
unittests. You need enough to move the needle on parsing.
2. Import that file, and build the main file with and without the 
-unittest flag.

3. This should not actually compile the unittests, but just parse them.

Using phobos as a test case is rife with things that may be contributing 
besides the parser.


-Steve


Re: Phobos Unittest

2021-09-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/4/21 7:43 AM, Johan wrote:

On Saturday, 4 September 2021 at 03:18:01 UTC, Paul Backus wrote:

On Saturday, 4 September 2021 at 00:09:37 UTC, H. S. Teoh wrote:
This is related to the bogonity of the current behaviour of 
-unittest, which compiles *all* unittests of *all* imported modules, 
even when you're compiling user code that has no interest in Phobos 
unittests.


Well, no; it compiles all unittests of all *compiled* modules, not all 
*imported* modules. So it does not actually include Phobos unittests.


[...]

As Steven Schveighoffer [pointed out][1], Phobos unittests are never 
included in user code, regardless of whether `StdUnittest` is used.


The "never" is false, https://d.godbolt.org/z/c4oeYM7rG

Unittests inside template code will be added to user code, unless the 
compiler has determined that the template is already instantiated in 
Phobos code (the "template culling" that the frontend does, whose 
behavior is not easily influenced by the programmer).


It's always included (or at least it was when I last looked at it), as 
-unittest implies some form of -allinst. There was some effort to fix 
this, but I can't remember if the outcome was that it was merged or not.


-Steve


Re: Phobos Unittest

2021-09-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/4/21 5:42 AM, Per Nordlöw wrote:

On Saturday, 4 September 2021 at 03:18:01 UTC, Paul Backus wrote:
As Steven Schveighoffer [pointed out][1], Phobos unittests are never 
included in user code, regardless of whether `StdUnittest` is used.


Yes, but they are lexed and parsed, right?


Yes, and I think this is trivially so for any versioned code in the file.

Note that lexing and parsing is extremely quick, and I wouldn't focus on 
trying to trim this out, you won't get much performance out of that.


-Steve


Re: Run-time setting of immutable variable?

2021-09-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/2/21 1:17 PM, DLearner wrote:


I am looking for a mutable Arr but would like an immutable ArrPtr.


Then you want const not immutable.

Here is the reason:

```d
void main()
{
int x = 5;
immutable int *ptr = cast(immutable int *)
assert(*ptr == 5); // ok
x = 6;
assert(*ptr == 5); // what happens here?
}
```

Depending on optimizations and compiler constant folding, that second 
assert may pass.


immutable means "I can never change and *everything I point at* can 
never change". The compiler is free to use this knowledge to avoid 
redoing calculations it has already done. I tknows that `*ptr == 5` 
already, and that can never change, so it just doesn't even bother with 
the second assert.


However, make ptr *const*, and now not only do you not need the cast, 
but the second assert will fail as expected.



```
`Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's 
immutable.

```
Surely there is no inconsistency - at run time the array is in a fixed 
place,  so ArrPtr is (or at least should be) a constant, but the 
contents of the array

can vary as the program runs.


In D, const and immutable are transitive, which means that you can't 
have a pointer that is const, but allows changing what it points at. So 
while a const pointer *may* work for your purposes, you may want a 
specialized type, or a property function. It depends on how you intend 
to use `ArrPtr`. Others have given good answers to this problem.


-Steve


Re: Run-time setting of immutable variable?

2021-09-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/2/21 12:01 PM, DLearner wrote:
Suppose there is a variable that is set once per run, and is (supposed) 
never to be altered again.  However, the value to which it is set is not 
known at compile time.

Example below, variable is 'ArrPtr';
```
ubyte[10] Arr;

// immutable void* ArrPtr;
void* ArrPtr;

void main() {

    ArrPtr = cast(void*)Arr[0];

// 

}
```
Is there a way of getting D to guarantee that ArrPtr is never modified 
after

```
    ArrPtr = cast(void*)Arr[0];
```]


You shouldn't be doing this. `Arr` is not immutable, so `ArrPtr` 
shouldn't point at it if it's immutable.


If you want to guarantee that `ArrPtr` never changes once set, yet still 
want it to point at mutable data, you need to use a type that does that 
(like a head mutable or "write once" type), which I believe doesn't 
exist in phobos.


If you don't actually need to mutate the data via `ArrPtr`, you can make 
it const, and use H.S. Teoh's solution. But you should not use 
immutable, as the compiler implies that data pointed at is also 
immutable (and of course, you won't need casting). Make sure you use 
regular `static this`, not `shared static this`, as your fields are 
thread-local, not shared.


-Steve


Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?

2021-09-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/31/21 8:40 PM, someone wrote:

On Tuesday, 31 August 2021 at 14:06:32 UTC, Steven Schveighoffer wrote:

The generation of code to output the page depends on the diet file 
format (i.e. code islands are designated by the leading `-`).



However, vibe-d does not require using the diet template system.


Does that means I can still get the code islands resolved on a, say, 
plain-XHTML file ?


Or does that means that I should output HTML/XHTML from my own functions 
instead ?


Vibe just provides an output range for use in diet. You can use 
anything, including just writing the data yourself, or using an 
alternative template system.


Given how templating systems work (and how D allows strings to be used 
as code using mixins), it's likely pretty trivial to write a simple 
templating system to do this. All you need is an escape protocol that 
is unlikely to appear in HTML, and you can probably get away with a 10 
line function that doesn't need to actually parse the HTML.


Probably. Bit I am not a huge fan of modifying libraries for minor 
functionality fixes (unless is really really necessary). For whatever 
reasons I already have custom nginx builds etc etc so I do not want to 
keep tracking and fixing more software -in the end is a pain-in-the-ass.


You aren't modifying anything. Vibe-d provides default access to 
diet-ng, but you have no obligation to use it. Just use the output range 
(`HTTPServerResponse.bodyWriter`) and hook up your preferred templating 
system.


I think you are misunderstanding the architecture of vibe. There is no 
need to replace anything inside vibe to use a different templating 
system, it does not depend on diet at all, just provides default access.


The views directory isn't exactly special either (though there may be 
code in dub that deals with looking at modification times), nor is the 
extension `.dt`.


Most of the diet compiler is dealing with transforming the pug format 
into HTML, and proper string interpolation. The code island stuff is 
quite trivial (just copied as-is).


Oh, and I realized I forgot about string interpolation. You definitely 
want a way to change D expressions into string output. You can still do 
this with code-islands, but a good template system would handle the 
boilerplate for you.


Which leads me to -- diet really should be split into 2 parts, one that 
handles the pug parsing and compiling, and one that handles proper 
string interpolation. Then you could leverage that second part.


-Steve


Re: Module import incompatibility

2021-08-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/31/21 11:17 AM, Paul Backus wrote:

On Tuesday, 31 August 2021 at 14:09:01 UTC, Steven Schveighoffer wrote:


Are you sure this is the problem? `PdfSurface` is not a valid 
identifier here except for the class. In order to access the package, 
you need to use `cairo.PdfSurface`.


Must've changed since you last checked:

```d
// main.d
import example;

void main()
{
     // Error: incompatible types for `(module example) == (42)`: `void` 
and `int`

     assert(example == 42);
}
```
```d
// example.d
int example = 42;
```

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



That is a top-level module that has an equivalent name inside. I did say 
"*as long as* it wasn't a top-level module"


```d
// main.d
import pkg.mod;

void main()
{
   assert mod = 42;
}

// example.d
module pkg.mod;
int mod = 42;
```

works fine

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

This is why I always try to use a top-level package instead of a module 
(especially with a common name).


-Steve


Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?

2021-08-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/30/21 8:09 PM, someone wrote:
Regarding vibe.d I think I'll give it a try (maybe placing it behind 
nginx at first) since I do really got a good first-impression ... kudos 
to the developers/maintainers :)


I like the idea of having D at my disposal within a web page, actually, 
it is a terrific feature to say the least.


What I do not like (even a bit) are the pseudo-HTML DIET templates. I 
can understand they can make life easy for some, but I am not the guy 
having any trouble writing well-good-structured HTML/XHTML/XML/etc to 
begin with, nor I am the kind of guy grunting because I will be forced 
to write closing tags and the like.


That being said, my specific question is:

Can I use vibe.d *without* DIET templates manually writing say, XHTML 
1.1 pages, *while having D* at my disposal with the - prefixes I have 
seen so far ?


The generation of code to output the page depends on the diet file 
format (i.e. code islands are designated by the leading `-`).


However, vibe-d does not require using the diet template system. There 
are others which probably do what you want (search on code.dlang.org), 
but I'm a huge fan of diet templates (I actually prefer writing 
non-template html that way), so I don't have any experience with others.


Given how templating systems work (and how D allows strings to be used 
as code using mixins), it's likely pretty trivial to write a simple 
templating system to do this. All you need is an escape protocol that is 
unlikely to appear in HTML, and you can probably get away with a 10 line 
function that doesn't need to actually parse the HTML.


-Steve


Re: Module import incompatibility

2021-08-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/31/21 8:57 AM, frame wrote:

On Tuesday, 31 August 2021 at 12:37:51 UTC, bauss wrote:

On Tuesday, 31 August 2021 at 12:26:28 UTC, frame wrote:

I'm sure it was asked before but can't find the thread:

How to deal best with an older library that uses the same class name 
as module name?

I get a lot of

`Error: module ABC from file ...ABC.d must be imported with 'import 
ABC'`


Do I need to rename all modules?


The problem is that the file doesn't have a module statement so the 
compiler tries to resolve the module name from the import but is 
unable to resolve that properly.


No, it has one, eg:

```d
module cairo.PdfSurface;
```

but the filename is PdfSurface.d and class name also :\




Are you sure this is the problem? `PdfSurface` is not a valid identifier 
here except for the class. In order to access the package, you need to 
use `cairo.PdfSurface`.


Tango was full of stuff like this, and it worked fine *as long as* it 
wasn't a top-level module.


-Steve


Re: vibe.d community/forum/whatever ?

2021-08-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/29/21 10:39 PM, someone wrote:

https://forum.rejectedsoftware.com/groups/rejectedsoftware.vibed/

I've been reading vibe.d tour and some documentation today to get some 
first impressions. https://vibed.org/community pointed to the link above 
... but it seems it is full of crap.


It used to be moderated somewhat, but I think they gave up (99% of the 
messages were porn or spam). Just post here instead, or you can join the 
[Community discord](https://discord.gg/bMZk9Q4) for more "live" help.


-Steve


Re: Is it legal to remove a key from associative array while iterating over aa.keys if a foreach loop?

2021-08-29 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/29/21 5:02 AM, Mike Parker wrote:

On Sunday, 29 August 2021 at 08:55:44 UTC, realhet wrote:




Is it safe, or do I have to take a snapsot of the keys range like 
this? ->


You shouldn't remove anything when iterating over `.keys` or `.values`. 
Use `.byKey` and `.byValue` instead to get ranges that are independent 
of the aa.


This is exactly the opposite!

The `.keys` property makes a *copy* of all the keys and puts them into 
an array. Same thing with `.values`. It is perfectly safe to remove 
anything  from the associative array while iterating one of those arrays.


The opposite is true for `.byKey` and `.byValue`. Those yield a range 
iterating over the actual data in the associative array. Removing an 
element while iterating one of those could potentially iterate over null 
or stale data, do not do this. While this might work out in some tests, 
eventually you will get bit by this, especially if you remove an element 
you are currently iterating.


-Steve


Re: DUB: How to link an external library on Windows 10?

2021-08-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/27/21 11:43 AM, Ki Rill wrote:

On Friday, 27 August 2021 at 15:24:14 UTC, Steven Schveighoffer wrote:
I suspect your MSVC installation is bad, or there are some other 
switches causing problems.




Hmm... well, I will use the default setup and think about it later.

I mostly use Linux, Windows realm is an uncharted territory for me.


Take my diagnoses with a grain of salt -- I mostly use MacOS and Linux, 
and I'm mostly lost on Windows. I was proficient with Visual C++ 5 or so 
a long time ago ;)


-Steve


Re: DUB: How to link an external library on Windows 10?

2021-08-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/27/21 11:19 AM, Ki Rill wrote:

On Friday, 27 August 2021 at 14:52:15 UTC, Mike Parker wrote:

On Friday, 27 August 2021 at 14:46:56 UTC, Ki Rill wrote:

On Friday, 27 August 2021 at 13:54:18 UTC, Steven Schveighoffer wrote:

[...]


How do I tell DUB where to look for `raylibdll.lib` and `raylib.dll`? 
Via `lflags` section? What if I put them in a different folder 
instead of the project's directory?


Yes. The path goes in the lflags directive using whatever the 
linker-specific flag is. I assume for lld it's `-Lpath`. For MS link 
it's `/LIBPATH:path`.


To clarify, the .dll file's path is not embedded into the binary. You 
have to add it's path to your "Path" environment variable in order for 
your game to load it.


But you do need the /LIBPATH option to tell it where to find the .lib file.



I've added lfags:
```
"lflags": ["/LIBPATH:C:\\Users\\Username\\Desktop\\test\\source\\"]
```

But now it cannot find the following:
```
msvcrt120.lib
OLDNAMES.lib
shell32.lib
```

I think `lfags` overrides the default search path and I need to add it 
manually as well. But what is that path on Windows?


That shouldn't happen. I've never had to tell it where the default 
libraries are. For sure the lflags does NOT override the default library 
search paths.


I suspect your MSVC installation is bad, or there are some other 
switches causing problems.


-Steve


Re: DUB: How to link an external library on Windows 10?

2021-08-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/27/21 10:35 AM, Ki Rill wrote:

On Friday, 27 August 2021 at 13:54:18 UTC, Steven Schveighoffer wrote:
In the end, I got it to build and run, but I'd highly recommend just 
linking against the `raylibdll.lib` and using the dll.




Steve, thank you! I got it working with `raylibdll.lib`!


Yes, either 3.5.0 or 3.7.0, they now build with 2 types of libs, static 
and dynamic. The raylib.lib file is for static linking, the 
raylibdll.lib file is for DLL.


Glad you got it working!

4. put `raylib.dll` and `raylibdll.lib` into your project's folder (into 
the same directory, where you have `dub.json`)


You know, I taught a class using raylib and D (I learned a lot from your 
video series, thanks!), and I didn't even think about just copy the 
libraries to your project directory as a "step". Instead I had them put 
in the /LIBDIR flags to wherever they installed it.


This way is MUCH easier, I think I'll switch to that.

dub in general has some rough edges when linking against libraries that 
aren't in default locations. Having to edit the dub.json file is sub-par.


-Steve


Re: DUB: How to link an external library on Windows 10?

2021-08-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/27/21 9:21 AM, Ki Rill wrote:
I have a Raylib project on Windows using DUB. I've added raylib-d via 
`dub add`. But what I can't figure out is how to tell DUB to link 
against raylib library.


I have the following project structure:
```
-> source
---> app.d
-> libraylib.a
-> raylib.dll
-> etc...
```

I'd like to use either .a or .dll. Do you have any ideas?


I spent a lot of time trying to figure this out (someone in discord 
really wanted to link statically for some reason). I FINALLY got a 
statically linked exe, but it's not worth the effort. I had to:


1. update my msvc build tools to match what was used for the official 
release (alternatively, you can rebuild the raylib library with your 
tools, otherwise you get cryptic errors like `fatal error C1900: Il 
mismatch between 'P1' version '20210113' and 'P2' version '20190715'`).

2. pass in cryptic linker options like `/NODEFAULTLIB:libcmt`, etc.
3. Link against extra libraries until the linker errors disappear 
(google search for missing symbols to see what libraries those symbols 
are in).


My eventual resulting dub.json looked like (you can guess where I put 
things):


```json
{
"name": "rps-explosion",
"dependencies": {
"jsoniopipe": "~>0.1.3",
"enet-d": "~>0.0.1",
"raylib-d": "~>3.1.0"
},
"libs": ["enet", "raylib", "ws2_32", "winmm", "msvcrt", "user32", 
"gdi32"],

"lflags": ["/LIBPATH:C:\\dprojects\\enet-1.3.17",
"/LIBPATH:C:\\dprojects\\raylib-3.7.0_win64_msvc16\\lib", 
"/NODEFAULTLIB:libcmt", "/NODEFAULTLIB:libvcruntime"]

}
```

This config also included `enet-d` so some of the linker options are for 
that lib.


In the end, I got it to build and run, but I'd highly recommend just 
linking against the `raylibdll.lib` and using the dll.


-Steve


Re: A way to mixin during runtime?

2021-08-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/27/21 6:34 AM, Kirill wrote:

On Friday, 27 August 2021 at 09:51:46 UTC, Mathias LANG wrote:

On Friday, 27 August 2021 at 06:52:10 UTC, Kirill wrote:

Is there a way to do mixin or similar during runtime?

I'm trying to read a csv file and extract data types. Any ideas on 
how this should be approached in D are greatly appreciated.


You cannot mixin at runtime. However, it is fairly easy to map a 
finite and CT-know set of argument to runtime arguments via `static 
foreach`.
Could you give us example of the content of your CSV file and what you 
are trying to do ?


Each csv file will be different.

For example:
```
name;surname;age;grade
Alex;Wong;18;87
John;Doe;19;65
Alice;Doe;18;73
etc...
```

I'd like to extract the data types automatically. For instance, if using 
tuples:

```
Tuple!(string, string, int, int) ...
```
instead I'd like to have:
```
auto mytuple = read_csv(path); // returns Tuple!(string, string, int, 
int)[]

```


So you can't build "new types" at runtime that are usable after your 
code is compiled. But there are options:


1. You can parse the CSV at compile-time using `import("types.csv");` 
and then processing the resulting string using CTFE (not sure if std.csv 
does this, but I'd expect it to). Then you can use the resulting thing 
to generate string mixins that can generate types. This has the drawback 
that you need to recompile when your csv input changes.


2. You can create a dynamic type that deals with the CSV data. It looks 
from your CSV data you are inferring the "type" from the data itself, 
which is complex in itself. In this case, you'd use it kind of like a 
JSON object, where you index the fields by name instead of using 
`obj.name`, and you'd have to extract the type dynamically from the type 
inference you'd have to write. This is pretty much what std.csv does, 
though you can dress it up a bit more.


Without the CSV telling you types, it's hard to make something "easy". I 
have written code that extracts from JSON data and database data 
serializable struct types, and builds a D file, but it's never 
clean-cut, and sometimes you have to hand-edit that stuff. This is about 
as "easy" as it gets, just have the computer do most of the heavy 
lifting, and then massage it into something usable.


-Steve


Re: A little help with Ranges

2021-08-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/27/21 12:41 AM, Merlin Diavova wrote:

On Friday, 27 August 2021 at 04:01:19 UTC, Ali Çehreli wrote:

On 8/26/21 7:17 PM, Merlin Diavova wrote:


[...]


Then the operations downstream will not produce any results. For 
example, the array will be empty below:


import std.stdio;
import std.range;
import std.algorithm;
import std.string;
import std.functional;

void main() {
  auto significantLines = stdin
  .byLineCopy
  .map!strip
  .filter!(not!empty)
  .filter!(line => line.front != '#')
  .array;

  if (significantLines.empty) {
    writeln("There were no significant lines.");

  } else {
    writefln!"The lines: %-(\n%s%)"(significantLines);
  }
}

Ali


And there it is!

I was missing

```d
.filter!(not!empty)
```

My code now works exactly how I wanted. Thanks!


Be careful with this! `not!empty` is *only* working because you are 
using arrays (where `empty` is a UFCS function defined in std.range). 
Other ranges this will not work on. Instead, I would recommend a lambda 
(which will work with arrays too):


```d
.filter!(r => !r.empty)
```

-Steve


Re: foreach() behavior on ranges

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 12:46 PM, Joseph Rushton Wakeling wrote:

On Wednesday, 25 August 2021 at 10:59:44 UTC, Steven Schveighoffer wrote:
structs still provide a mechanism (postblit/copy ctor) to properly 
save a forward range when copying, even if the guts need copying 
(unlike classes). In general, I think it was a mistake to use `.save` 
as the mechanism, as generally `.save` is equivalent to copying, so 
nobody does it, and code works fine for most ranges.


Consider a struct whose internal fields are just a pointer to its "true" 
internal state.  Does one have any right to assume that the 
postblit/copy ctor would necessarily deep-copy that?


In a world where copyability means it's a forward range? Yes. We aren't 
in that world, it's a hypothetical "if we could go back and redesign".


If that struct implements a forward range, though, and that pointed-to 
state is mutated by iteration of the range, then it would be reasonable 
to assume that the `save` method MUST deep-copy it, because otherwise 
the forward-range property would not be respected.


With that in mind, I am not sure it's reasonable to assume that just 
because a struct implements a forward-range API, that copying the struct 
instance is necessarily the same as saving the range.


Technically this is true. In practice, it rarely happens. The flaw of 
`save` isn't that it's an unsound API, the flaw is that people get away 
with just copying, and it works 99.9% of the time. So code is simply 
untested with ranges where `save` is important.


Indeed, IIRC quite a few Phobos library functions program defensively 
against that difference by taking a `.save` copy of their input before 
iterating over it.


I'd be willing to bet $10 there is a function in phobos right now, that 
takes forward ranges, and forgets to call `save` when iterating with 
foreach. It's just so easy to do, and works with most ranges in existence.




What should have happened is that input-only ranges should not have 
been copyable, and copying should have been the save mechanism. Then 
it becomes way way more obvious what is happening. Yes, this means 
forgoing classes as ranges.


I think there's a benefit of a method whose definition is explicitly "If 
you call this, you will get a copy of the range which will replay 
exactly the same results when iterating over it".  Just because the 
meaning of "copy" can be ambiguous, whereas a promise about how 
iteration can be used is not.


The idea is to make the meaning of a range copy not ambiguous.

-Steve


Re: scope(exit) with expected library

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 10:58 AM, WebFreak001 wrote:



Hm I'm not quite seeing how the error handler is related to an "Expected 
type interface" that the compiler could expect.


This would be without compiler changes.

Currently with exceptions the scope things are implemented using 
try-catch-finally, this would be even simpler:


```d
scope(exit) exit();
scope(success) success();
scope(failure) failure();

return something();
```

lowers to

```d
auto ret = something();
if (ret.isError) failure();
if (!ret.isError) success();
exit();
return ret;
```

for all return statements.

I might be missing some obvious drawbacks here but I think this sounds 
reasonable and comparable with the try-catch-finally lowering.


It does sound pretty reasonable. But overloading these existing features 
might make things confusing.




As Paul Backus suggested the compiler could check if the return type has 
for example `is(typeof(return.isError) : bool)` and maybe also if the 
function is `nothrow`.


Another approach is to let the compiler deal with the error handling and 
not muddy your return type. Swift does something similar, where it 
rewrites the throw/catch into a standard return and doesn't do actual 
thrown exceptions. There are some caveats, but if we could fit this kind 
of error handling into mostly-similar syntax (i.e. the same ease of 
exceptions without the actual problems that exceptions and stack 
unwinding bring), it might make things much easier to transition.


-Steve


Re: scope(exit) with expected library

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 10:42 AM, Steven Schveighoffer wrote:



I think it's possible to work with some mechanics that aren't 
necessarily desirable. Something like:




One has to weigh how much this is preferred to actual exception handling...

If something like DIP1008 could become usable, it might alleviate even 
the need for such things.


-Steve


Re: scope(exit) with expected library

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 10:22 AM, Paul Backus wrote:

On Wednesday, 25 August 2021 at 14:04:54 UTC, WebFreak001 wrote:
Would it be possible to extend `scope(exit)` and `scope(success)` to 
trigger properly for functions returning `Expected!T` as defined in 
the [expectations](https://code.dlang.org/packages/expectations) and 
[expected](https://code.dlang.org/packages/expected) DUB libraries?


For example is it possible to make this work as expected:
```d
Expected!int divide(int a, int b) nothrow
{
    scope (failure) writeln("division failed");
    scope (success) writeln("division succeeded");

    if (b == 0) return err!int("division by zero");
    return ok(a / b);
}
```


Probably the only principled way to make this work would be to define 
some kind of "concept"/structural interface that's recognized by the 
compiler to mean "this is an error-handling type", in the same way that 
the compiler recognizes `empty`/`front`/`popFront` to mean "this is an 
iterable type".


Even then, it would require some pretty invasive language changes (and 
some pretty gnarly code in the compiler), but it's at least 
*theoretically* possible.


I think it's possible to work with some mechanics that aren't 
necessarily desirable. Something like:


```d
ErrorHandler error = registerErrorHandler;
error.onFailure({writeln("division failed");});
error.onSuccess({writeln("division succeeded");});

...
```

On returning `err`, the registration would trigger a flag saying an 
error is occurring, and call the right callback when `ErrorHandler` is 
destructing. The cleanup of the return value would clean up the error 
condition. It would be messy and likely brittle.


I've also advocated in the past that it would be nice to have access to 
the things that are causing the success, failure, etc.


Like `scope(failure, exception) writeln("Exception being thrown is ", 
exception)`


Could be extended to:

```d
scope(success, r) if(r.isError) writeln("division failed");
  else  writeln("division succeeded");
```

That `scope(success)` kinda sucks though...

-Steve


Re: foreach() behavior on ranges

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 7:26 AM, Alexandru Ermicioi wrote:

On Wednesday, 25 August 2021 at 11:04:35 UTC, Steven Schveighoffer wrote:
It never has called `save`. It makes a copy, which is almost always 
the equivalent `save` implementation.




Really?

Then what is the use for .save method then?
The only reason I can find is that you can't declare constructors in 
interfaces hence the use of the .save method instead of copy constructor 
for defining forward ranges.


The `save` function was used to provide a way for code like 
`isForwardRange` to have a definitive symbol to search for. It's also 
opt-in, whereas if we used copying, it would be opt-out.


Why a function, and not just some enum? Because it should be something 
that has to be used, not just a "documenting" attribute if I recall 
correctly.


Keep in mind, UDAs were not a thing yet, and compile-time introspection 
was not as robust as it is now. I'm not even sure you could disable copying.




We have now two ways of doing the same thing, which can cause confusion. 
Best would be then for ranges to hide copy constructor under private 
modifier (or disable altoghether), and force other range wrappers call 
.save always, including foreach since by not doing so we introduce 
difference in behavior between ref and value forward ranges (for foreach 
use).


There would be a huge hole in this plan -- arrays. Arrays are the most 
common range anywhere, and if a forward range must not be copyable any 
way but using `save`, it would mean arrays are not forward ranges.


Not to mention that foreach on an array is a language construct, and 
does not involve the range interface.


-Steve


Re: foreach() behavior on ranges

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 6:06 AM, Alexandru Ermicioi wrote:

On Wednesday, 25 August 2021 at 08:15:18 UTC, frame wrote:

I know, but foreach() doesn't call save().


Hmm, this is a regression probably, or I missed the time frame when 
foreach moved to use of copy constructor for forward ranges.


Do we have a well defined description of what input, forward and any 
other well known range is, and how it does interact with language features?


For some reason I didn't manage to find anything on dlang.org.


It never has called `save`. It makes a copy, which is almost always the 
equivalent `save` implementation.


-Steve


Re: foreach() behavior on ranges

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 4:31 AM, frame wrote:

On Tuesday, 24 August 2021 at 21:15:02 UTC, Steven Schveighoffer wrote:
I'm surprised you bring PHP as an example, as it appears their foreach 
interface works EXACTLY as D does:


Yeah, but the point is, there is a rewind() method. That is called every 
time on foreach().


It seems what you are after is forward ranges. Those are able to 
"rewind" when you are done with them. It's just not done through a 
rewind method, but via saving the range before iteration:


```d
foreach(val; forwardRange.save)
{
   ...
   break;
}

// forwardRange hasn't been iterated here
```

-Steve


Re: foreach() behavior on ranges

2021-08-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/25/21 6:06 AM, Joseph Rushton Wakeling wrote:

On Tuesday, 24 August 2021 at 09:15:23 UTC, bauss wrote:
A range should be a struct always and thus its state is copied when 
the foreach loop is created.


That's quite a strong assumption, because its state might be a reference 
type, or it might not _have_ state in a meaningful sense -- consider an 
input range that wraps reading from a socket, or that just reads from 
`/dev/urandom`, for two examples.


Deterministic copying per foreach loop is only guaranteed for forward 
ranges.


structs still provide a mechanism (postblit/copy ctor) to properly save 
a forward range when copying, even if the guts need copying (unlike 
classes). In general, I think it was a mistake to use `.save` as the 
mechanism, as generally `.save` is equivalent to copying, so nobody does 
it, and code works fine for most ranges.


What should have happened is that input-only ranges should not have been 
copyable, and copying should have been the save mechanism. Then it 
becomes way way more obvious what is happening. Yes, this means forgoing 
classes as ranges.


-Steve


Re: foreach() behavior on ranges

2021-08-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/24/21 2:12 PM, frame wrote:
You can call `popFront` if you need to after the loop, or just before 
the break. I have to say, the term "useless" does not even come close 
to describing ranges using foreach in my experience.


I disagree, because foreach() is a language construct and therefore it 
should behave in a logic way. The methods are fine in ranges or if 
something is done manually. But in case of foreach() it's just unexpected.


I can't agree at all. It's totally expected.

If you have a for loop:

```d
int i;
for(i = 0; i < someArr.length; ++i)
{
   if(someArr[i] == desiredValue) break;
}
```

You are saying, "compiler, please execute the `++i` when I break from 
the loop because I already processed that one". How can that be 
expected? I would *never* expect that. When I break, it means "stop the 
loop, I'm done", and then I use `i` which is where I expected it to be.


It becomes useless for foreach() because you can't rely on them if other 
code breaks the loop and you need to use that range, like in my case. 
But also for ranges - there is no need for a popFront() if it is not 
called in a logic way. Then even empty() could fetch next data if 
needed. It only makes sense if language system code uses it in a 
strictly order and ensures that this order is always assured.


There is no problem with the ordering. What seems to be the issue is 
that you aren't used to the way ranges work.


What's great about D is that there is a solution for you:

```d
struct EagerPopfrontRange(R)
{
   R source;
   ElementType!R front;
   bool empty;
   void popFront() {
 if(source.empty) empty = true;
 else {
front = source.front;
source.popFront;
 }
   }
}

auto epf(R)(R inputRange) {
   auto result = EagerPopfrontRange!R(inputRange);
   result.popFront; // eager!
   return result;
}

// usage
foreach(v; someRange.epf) { ... }
```

Now if you break from the loop, the original range is pointing at the 
element *after* the one you last were processing.



It's not a bug. So there is no need to "handle" it.

The pattern of using a for(each) loop to align certain things occurs 
all the time in code. Imagine a loop that is looking for a certain 
line in a file, and breaks when the line is there. Would you really 
want the compiler to unhelpfully throw away that line for you?


I don't get this point. If it breaks from the loop then it changes the 
scope anyway, so my data should be already processed or copied. What is 
thrown away here?
Why does the loop have to contain all your code? Maybe you have code 
after the loop. Maybe the loop's purpose is to align the range based on 
some criteria (e.g. take this byLine range and prime it so it contains 
the first line of the thing I'm looking for).






And if that is what you want, put `popFront` in the loop before you 
exit. You can't "unpopFront" something, so this provides the most 
flexibility.




Yes, this is the solution but not the way how it should be. If the 
programmer uses the range methods within the foreach-loop then you would 
expect some bug. There shouldn't be a need to manipulate the range just 
because I break the foreach-loop.


You shouldn't need to in most circumstances. I don't think I've ever 
needed to do this. And I use foreach on ranges all the time.


Granted, I probably would use a while loop to align a range rather than 
foreach.




Java, for example just uses next() and hasNext(). You can't run into a 
bug here because one method must move the cursor.


This gives a giant clue as to the problem -- you aren't used to this. 
Java's iterator interface is different than D's. It consumes the element 
as you fetch it, instead of acting like a pointer to a current element. 
Once it gives you the element, it's done with it.


D's ranges are closer to a C++ iterator pair (which is modeled after a 
pair of pointers).


PHP has a rewind() method. So any foreach() would reset the range or 
could clean up before next use of it.


I'm surprised you bring PHP as an example, as it appears their foreach 
interface works EXACTLY as D does:


```php
$arriter = new ArrayIterator(array(1, 2, 3, 4));
foreach($arriter as $val) { if ($val == 2) break; }
print($arriter->current()); // 2
```

But D just lets your range in an inconsistent state between an iteration 
cycle. This feels just wrong. The next foreach() would not continue with 
popFront() but with empty() again - because it even relies on it that a 
range should be called in a given order. As there is no rewind or 
exit-method, this order should be maintained by foreach-exit too, 
preparing for next use. That's it.


You don't see a bug here?



I believe the bug is in your expectations. While Java-like iteration 
would be a possible API D could have chosen, it's not what D chose.


-Steve


Re: foreach() behavior on ranges

2021-08-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/24/21 4:36 AM, frame wrote:
Consider a simple input range that can be iterated with empty(), front() 
and popFront(). That is comfortable to use with foreach() but what if 
the foreach loop will be cancelled? If a range isn't depleted yet and 
continued it will supply the same data twice on front() in the next use 
of foreach().


For some reason, foreach() does not call popFront() on a break or 
continue statement. 


continue calls `popFront`. break does not.

There is no way to detect it except the range itself 
tracks its status and does an implicit popFront() if needed - but then 
this whole interface is some kind of useless.


You can call `popFront` if you need to after the loop, or just before 
the break. I have to say, the term "useless" does not even come close to 
describing ranges using foreach in my experience.


There is opApply() on the other hand that is designed for foreach() and 
informs via non-0-result if the loop is cancelled - but this means that 
every range must implement it if the range should work in foreach() 
correctly?


`opApply` has to return different values because it needs you to pass 
through its instructions to the compiler-generated code. The compiler 
has written the delegate to return the message, and so you need to pass 
through that information. The non-zero result is significant, not just 
non-zero. For instance, if you end with a `break somelabel;` statement, 
it has to know which label to go to.


The correct behavior for `opApply` should be, if the delegate returns 
non-zero, return that value immediately. It should not be doing anything 
else. Would you be happy with a `break somelabel;` actually triggering 
output? What if it just continued the loop instead? You don't get to 
decide what happens at that point, you are acting as the compiler.


This is very inconsistent. Either foreach() should deny usage of ranges 
that have no opApply() method or there should be a reset() or cancel() 
method in the interfaces that may be called by foreach() if they are 
implemented.


How do you handle that issue? Are your ranges designed to have this bug 
or do you implement opApply() always?


It's not a bug. So there is no need to "handle" it.

The pattern of using a for(each) loop to align certain things occurs all 
the time in code. Imagine a loop that is looking for a certain line in a 
file, and breaks when the line is there. Would you really want the 
compiler to unhelpfully throw away that line for you?


And if that is what you want, put `popFront` in the loop before you 
exit. You can't "unpopFront" something, so this provides the most 
flexibility.


-Steve


Re: Concurrency message passing

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/21 2:36 PM, JG wrote:
Thanks for the suggestions and explanations. I am not sure what to do in 
my case though. The situation is as follows. I have a struct that is 
populated via user input not necessarily at single instance (so that 
seems to rule out immutable). On the other
hand while it is being populate it is only accessible from one thread so 
that
makes using shared messy. After being populated it should be passed to 
the other thread and no references are kept.


You are allowed to cast to immutable if no other mutable references are 
used. I recommend using `assumeUnique`.


What I am doing currently is populating the struct and casting to shared 
when I push into a synchronized queue (no references to its data are 
kept in the first thread). Is what I am doing wrong and can it be 
achieved using message passing?


Yeah, build it like Ali says, and then cast in order to pass it.

-Steve


Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/21 2:11 PM, james.p.leblanc wrote:

Evening All,

Eponymous templates allow a nice calling syntax.  For example, "foo" 
here can
be called without needing the exclamation mark (!) at calling sites.  We 
see that

foo is restricting a, and b to be of the same type ... so far, so good.

auto foo(T)(T a, T b) { ... }

Now, suppose I need to restrict "T" only certain subsets of variable types.

I can imagine putting in some "static if" statements in my function body,
is one solution.  (Also a bit ugly as the allowed types might grow).

Is there a more elegant way, to do this?


[Template 
constraints](https://dlang.org/spec/template.html#template_constraints).


-Steve


Re: Non-consistent implicit function template specializations

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/21 2:07 PM, Rekel wrote:

On Tuesday, 17 August 2021 at 16:24:38 UTC, Steven Schveighoffer wrote:


All these are calling with array literals, which default to dynamic 
arrays, not static arrays.


I realise that is their default, though in this scenario they should (I 
believe) be used as static arrays. (This works for me in any case)


According to my tests, it prefers the `T` version over the static array 
version. Which leads me to believe that it prefers a dynamic array over 
a static one. In fact, if I comment out the `T` version, it doesn't 
compile. It literally will not pick that specialization, even if it can 
interpret the literal that way.


which is really bizarre, since if you do it without specializations, but 
just spelling out all the template components (as in your alternative 
workaround), it WILL pick that one over a dynamic array one.


-Steve


Re: Non-consistent implicit function template specializations

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/21 10:20 AM, Rekel wrote:
As my post was not the actual cause of my issue (my apology for the 
mistake), I think I have found the actual reason I'm currently having 
problems.
This seems to be related to a (seeming, I might be wrong) inability to 
specialize over both 1d and 2d arrays separately. (If constraining the 
length to values.)


This brings me to 2 questions.
1. How does one specialize a template for both 1d and 2d arrays at the 
same time?

2. Are there any plans to rework templates? like:
- Making `template TFoo(T : T[])` illegal. This makes little sense to me 
however I look at it, and as several people have advised against it it's 
confusing it's in the docs. (21.4.1)
- Changing the way priorities are set using specializations in general, 
to make them less pitfall-y.
- Allow for 2+d length specification. At the moment `T[][L]` works while 
`T[L][L]` does not seem to.


You should try out things individually to see if they at least work.



```d
void foo(T)(T a){...}

void foo(T:U[L], uint L)(T a){...}


This is an invalid specification, what is U? Did you mean:

void foo(T: U[L], U, uint L)(T a) {...}


void foo(T:U[L][L], uint L)(T a){...} // Never matched


Apart from another missing U, this is only a SQUARE 2d-array (both 
dimensions the same), your example below only calls with a 1x2 array.


void foo(T:U[L], U:V[L], V uint L)(T a){...} // Never matched 
(alternatively)


I don't think you need this, and I had to comment it out, or the 
compiler wouldn't build.




// Should work with
void main(string[] args) {
 foo([[1],[2]]);
 foo([1,2]);
 foo(1);
}
```


All these are calling with array literals, which default to dynamic 
arrays, not static arrays.


-Steve


Re: How to get element type of a slice?

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/21 8:21 AM, Ferhat Kurtulmuş wrote:

Hello folks,

Hope everyone is doing fine. Considering the following code, in the 
first condition, I am extracting the type Point from the slice Point[]. 
I searched in the std.traits, and could not find a neater solution 
something like ElementTypeOf!T. Is there any neater solution for it? 
Thanks in advance.


```d
     static if (isArray!VecPoint){
     VecPoint dummy;
     alias Point = typeof(dummy[0]);
     } else static if (isRandomAccessRange!VecPoint){
     alias ASeq2 = TemplateArgsOf!VecPoint;
     alias Point = ASeq2[0];
     } else
     static assert(0, typeof(VecPoint).stringof ~ " type is not 
supported");

```


If you want the element type of a range (i.e. the thing returned by 
`range.front`), you can use `ElementType!T` (from std.range.primitives).


This returns the element type of the range, which for every array 
*except* character arrays, gives you the element type of the array.


If you want always the element type of the array, even for auto-decoded 
ranges, use `ElementEncodingType!T`.


If you know it's an array, you can just use Paul's solution.

Your `isRandomAccessRange` branch seems very suspect.

-Steve


Re: Concurrency message passing

2021-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/21 7:05 AM, JG wrote:

Hi

I have a program with two threads. One thread produces data that is put 
in a queue
and then consumed by the other thread. I initially built a custom queue 
to do this, but thought this should have some standard solution in D? I 
looked at std.concurrency and thought that message passing could be 
used. However, the problem is that I get the following error.


Error: static assert:  "Aliases to mutable thread-local data not allowed."

I am not sure how to solve this.  Maybe message parsing isn't the 
correct solution?

Is there some standard solution to this in D?


Data with references needs to be marked either immutable or shared in 
order to be passed using std.concurrency. D is strict about not sharing 
thread-local data, because then you can use the type system to prove 
lock-free code is valid.


However, data that has no references (aliases) should be passable 
regardless of mutability, because you are passing a copy.


-Steve


Re: What exactly are the String literrals in D and how they work?

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

On 8/15/21 2:10 AM, rempas wrote:

So when I'm doing something like the following: `string name = "John";`
Then what's the actual type of the literal `"John"`?
In the chapter [Calling C 
functions](https://dlang.org/spec/interfaceToC.html#calling_c_functions) 
in the "Interfacing with C" page, the following is said:
Strings are not 0 terminated in D. See "Data Type Compatibility" for 
more information about this. However, string literals in D are 0 
terminated.


Which is really interesting and makes me suppose that `"John"` is a 
string literal right?
However, when I'm writing something like the following: `char *name = 
"John";`,

then D will complain with the following message:
Error: cannot implicitly convert expression `"John"` of type `string` 
to `char*`


Which is interesting because this works in C. If I use `const char*` 
instead, it will work. I suppose that this has to do with the fact that 
`string` is an alias for `immutable(char[])` but still this has to mean 
that the actual type of a LITERAL string is of type `string` (aka 
`immutable(char[])`).


Another thing I can do is cast the literal to a `char*` but I'm 
wondering what's going on under the hood in this case. Is casting 
executed at compile time or at runtime? So am I going to have an extra 
runtime cost having to first construct a `string` and then ALSO cast it 
to a string literal?


I hope all that makes sense and the someone can answer, lol


Lots of great responses in this thread!

I wanted to stress that a string literal is sort of magic. It has extra 
type information inside the compiler that is not available in the normal 
type system. Namely that "this is a literal, and so can morph into other 
things".


To give you some examples:

```d
string s = "John";
immutable(char)* cs = s; // nope
immutable(char)* cs2 = "John"; // OK!
wstring ws = s; // nope
wstring ws2 = "John"; // OK!
```

What is going on? Because the compiler knows this is a string *literal*, 
it can modify the type (and possibly the data itself) at will to match 
what you are assigning it to. In the case of zero-terminated C strings, 
it allows usage as a pointer instead of a D array. In the case of 
different width strings (wstring uses 16-bit code-units), it can 
actually transform the underlying data to what you wanted.


Note that even when you do lose that "literal" magic by assigning to a 
variable, you can still rely on D always putting a terminating zero in 
the data segment for a string literal. So it's valid to just do:


```d
string s = "John";
printf(s.ptr);


As long as you *know* the string came from a literal.

-Steve


Re: How to extend the string class to return this inside the square bracket?

2021-08-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/13/21 7:23 PM, Marcone wrote:

On Friday, 13 August 2021 at 23:08:07 UTC, jfondren wrote:

On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:


Isn't there some unario operator template that I can use with lambda 
to handle a string literal?


So, something other than an exact "lit"[0..this.xx(..)] syntax is fine?

What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` 
then?


What is a real example of something you want to do?


writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]);

indexOf()is just a simple example, not the goal. I want handle literal 
inside [] like it bellow, but in literal:


string x = "Hello World!";
writeln(x[x.indexOf("e")..x.indexOf("r")]);


Operator overloading is only available to custom types (structs or 
classes), and not to arrays.


You can create a type to do what you want.

e.g.:

```d
struct SliceByIndexOf
{
   string s;
   auto opIndex(size_t[2] idxs) {
  return SliceByIndexOf(s[ idxs[0] .. idxs[1]]);
   }
   size_t[2] opSlice(size_t dim : 0)(string s1, string s2) {
  import std.string;
  return [s.indexOf(s1), s.indexOf(s2)];
   }
string toString() { return s; }
}

auto sbio(string s) { return SliceByIndexOf(s); }

void main()
{
import std.stdio;
writeln("Hello World!".sbio["e" .. "r"]); // "ello Wo"
}
```

-Steve


Re: How to extend the string class to return this inside the square bracket?

2021-08-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/13/21 5:05 PM, Marcone wrote:
How to extend the string class to return this inside the square bracket 
the same way opDollar $ returns the length of the string? Thank you.


     import std;

     void main(){
     writeln("Hello World!"[0..this.indexOf("o")]);
     }


There is no string class to extend.

`$` is a special token the compiler changes to `arr.length` for arrays.

-Steve


Re: I do not understand copy constructors

2021-08-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/13/21 4:58 PM, Paul Backus wrote:

On Friday, 13 August 2021 at 15:26:15 UTC, Steven Schveighoffer wrote:
The issue is that you can't convert const (or immutable or mutable) to 
inout implicitly, and the member variable is inout inside an inout 
constructor. Therefore, there's no viable copy constructor to call for 
the member, and the outer copy constructor cannot be generated.


I'm not quite sure I follow this. Are you saying that the constructor 
call is typechecked as if it were written like this:


```d
this.field = this.field.__ctor(rhs.field);
```

...and not like this?

```d
this.field.__ctor(rhs.field);
```

Because I can see how the first version would involve an const-to-inout 
conversion, but the second version looks like it ought to work.


My point was just that `ref inout` normally binds to `ref const`.

Example:

```d
void foo(ref const int a)
{
  writeln("hi, a is ", a);
}

void bar(ref inout int b)
{
   foo(b); // fine
}
```

You implied in your statement that it was the ref-ness that prevents the 
call. Your simplified example was also a bit off, it was a double 
indirection of a ref array (which is definitely forbidden to be implicit 
cast).


But for constructors it's not the same. Essentially because constructors 
have different rules for what they can do with their inputs (the inout 
`this` parameter can be assigned to for the member's first assignment).


What I was trying to say (poorly) is that inside the inout copy ctor, 
you can actually call the const `A` copy constructor with an input of 
the other `inout A`. You just can't call it on the member (or assign it 
to the member), because that would allow some bad things to happen in 
some cases.


-Steve


Re: Help with Win32: PostQuitMessage(0) doesn't post WM_QUIT apparently, because the message loop is not exited.

2021-08-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/13/21 3:59 PM, Mike Parker wrote:

On Friday, 13 August 2021 at 16:18:06 UTC, Ruby The Roobster wrote:

Context for this: I am creating a module of my  own, and this is a 
class contained in the module.  You will notice that after calling 
this class' constructor anywhere in a Win32 API program, that the 
program doesn't close after the window is closed.


You're hanging in `Runtime.terminate`. That's because of your `Entity` 
destructor, specifically this line:


     entitytable.length -= 1;

Comment it out and the program exits successfully.

You aren't supposed to be manipulating GC-managed memory via class 
destructors. You can not rely on that memory being valid at the time 
that it's accessed in the destructor---the object may already have been 
destroyed. Nondeterministic destruction is the price you pay for letting 
the GC manager your object memory.


Of course, in this case, the problem will only crop up at termination 
since the array is declared at module scope so will be live up until the 
GC shuts down. But still, not something you should be doing.


The runtime will help you by throwing an error if you do anything that 
directly triggers an allocation, like calling `new` or performing an 
array append. But it won't help you with anything else.


Someone more versed than I with the GC innards may be able to answer 
whether an error should be thrown here as well, or if this goes under 
the undefined behavior category.


Well, subtracting the length doesn't do much, you aren't actually 
accessing the array block, you are just changing the reference (which 
lives in thread-local storage). I kind of feel like the whole entity 
table thing is not correct anyway. Did you (Mike) also comment out the 
`did` call? Because that looks more suspicious to me. What it is doing 
is going through all the entities from the removed one on and setting 
their id to 1 less. HOWEVER, it's not actually *moving* the entities 
down in the array.


So for instance, if you have 3 entities `[e(0), e(1), e(2)]` then what 
happens when you remove e(1) is it changes their ids to `[e(0), e(0), 
e(1)]` and then resizes the array to strip off the last one, so you get 
the destroyed entity still in the table, and the one that used to be 
e(2) out of the table (though its id is set to 1 now). The result will 
be `[e(0), e(0)]`, with the second one pointing to an invalid block.


However, you will NEVER have an entity be destroyed, because there is 
always a reference to it in the table! They will only get destroyed at 
the end, via `terminate` where things are destroyed deterministically.


I think you are right that he shouldn't be changing that `entitytable` 
thing in the dtor. I also think, the memory management being used there 
is super-sketchy. Without knowing why you need to keep the table around 
in the first place, I'm unsure how it should be fixed.


I suspect there is a memory access violation or some other issue that's 
causing it to crash rather than exit normally.


-Steve


Re: I do not understand copy constructors

2021-08-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/12/21 12:12 PM, Paul Backus wrote:
The reason for this is a bit subtle. Normally, `inout` can convert to 
`const`, so you might expect that the `const` copy constructor could be 
used to construct a copy of an `inout` object. However, copy 
constructors take their arguments by `ref`, and implicit conversions are 
not allowed for arguments passed to `ref` parameters. (I cannot find a 
citation in the spec for this, but you can verify it yourself.)


implicit const conversions are possible via a single ref, but not 
through a double reference. In this case, it's not the passing of the 
inout object to the const constructor.


The issue is that you can't convert const (or immutable or mutable) to 
inout implicitly, and the member variable is inout inside an inout 
constructor. Therefore, there's no viable copy constructor to call for 
the member, and the outer copy constructor cannot be generated.


As a side note, inout actually *can* bind to double references of any 
mutability, unlike const, which is a nice feature that is seldom talked 
about.


-Steve


Re: aliasing functions with function arguments as well ??

2021-08-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/13/21 11:04 AM, james.p.leblanc wrote:

Dear All,

How does one use 'alias' to incorporate function arguments as well?

(I believe this is possible, from some of the examples of aliasSeq, and
the traits.Parameters documentation.  However, I was unable to come up
with anything that works.)

What should replace the question marks (???) below?


double bar( int a, double x){
  return a*x:
}



template foo(T){
  static if ( is(T==int) ){
 alias ??? = ???
  }
  else{
 alias ??? = ???
  }
}

// when T == int, I desire the aliasing to produce resulting code:
foo( int a) = bar( int a, 42.33);

// when T == double, I desire:
foo( double x) = bar( 7, x);



Thanks kindly for any information!
James

PS I am aware of the "struct holding a function allowing multiple 
dispatch concept"
... while that would fit quite okay here in my simple example, it isn't 
appropriate

for my real use.



There isn't a way to alias it. You can wrap it though, and hope the 
inliner takes care of the difference:


```d
auto foo(T)(T arg)
{
   static if(is(T == int)) return bar(arg, 42.33);
   else return bar(7, arg);
}
```

-Steve


Re: I do not understand copy constructors

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

On 8/12/21 10:08 AM, Learner wrote:

On Thursday, 12 August 2021 at 13:56:17 UTC, Paul Backus wrote:

On Thursday, 12 August 2021 at 12:10:49 UTC, Learner wrote:


That worked fine, but the codebase is @safe:

```d
cast from `int[]` to `inout(int[])` not allowed in safe code
```

So copy constructors force me to introduce trusted methods, while 
that was not necessary with postblits?


A postblit would simply ignore the type qualifier--which can lead to 
undefined behavior. (Scroll down to the paragraph that begins "An 
unqualified postblit..." under ["Struct Postblits"][1] in the spec.) 
The copy constructor merely forces you to be honest about the safety 
of your code.


In your case, I would recommend encapsulating the unsafe cast in a 
function like the following:


```d
T[] dupWithQualifiers(T[] array)
{
    auto copy = array.dup;
    return (() @trusted => cast(T[]) copy)();
}
```

You can then use this function in place of `dup` in your copy 
constructor.


[1]: https://dlang.org/spec/struct.html#struct-postblit


Thank you, now everything is more clear.

A last question, if you do not mind, just to better understand inout. It 
seems a shortcut to avoid repeating the same function body for mutable, 
const, and immutable. Why the following code is not equal to the single 
inout constructor?


     struct A {
     int[] data;

     //this(ref return scope inout A rhs) inout { /*body*/ }

     this(ref return scope   Timestamp rhs) { /*body*/ }
     this(ref return scope const Timestamp rhs) const { /*body*/ }
     this(ref return scope immutable Timestamp rhs) immutable { 
/*body*/ }

     }
     Error: Generating an `inout` copy constructor for `struct B` 
failed, therefore instances of it are uncopyable


Inout is compatible only with inout, and not with the unrolled code it 
implies?


inout is not like a template. It's a separate qualifier that generates 
only one function (not 3 unrolled ones).


It's sort of viral like const is viral -- all underlying pieces have to 
support inout in order for you to write inout functions.


-Steve


Re: equivalent of std.functional.partial for templates?

2021-08-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On Wednesday, 11 August 2021 at 14:08:59 UTC, Paul Backus wrote:

On Wednesday, 11 August 2021 at 14:03:50 UTC, Paul Backus wrote:
On Wednesday, 11 August 2021 at 14:00:33 UTC, Steven 
Schveighoffer wrote:

I have a template function like this:

```d
auto foo(T, Args...)(Args args) {...}
```

If I try to bind the T only, and produce a partial template 
function which can accept any number of parameters, but has T 
already specified, I get an error, because instantiating 
`foo!T` means Args is length 0.


https://phobos.dpldocs.info/std.meta.ApplyLeft.html


Should have read further--this does not work with template 
functions due to [issue 1807.][1] My mistake.


[1]: https://issues.dlang.org/show_bug.cgi?id=1807


So first, I though ApplyLeft would work, but I convinced myself 
it was focused on applying the template to arguments 
individually, but that's just the example used. ApplyLeft is 
exactly what I'm looking for, but as you said (and as my example 
shows), it doesn't work in this case. It would be nice to have 
something that would work (or make ApplyLeft work via a compiler 
change).


Thanks for the nudge!

-Steve


equivalent of std.functional.partial for templates?

2021-08-11 Thread Steven Schveighoffer via Digitalmars-d-learn

I have a template function like this:

```d
auto foo(T, Args...)(Args args) {...}
```

If I try to bind the T only, and produce a partial template 
function which can accept any number of parameters, but has T 
already specified, I get an error, because instantiating `foo!T` 
means Args is length 0.


I was surprised not to see something in std.meta that could 
create this for me. In `std.functional` there is `partial` (which 
bizarrely only allows one parameter to be specified), but I don't 
see an equivalent for template parameters.


For functions, it seems IFTI can't see through to infer the 
template parameters of the alias, but you can have a function 
wrapper:


```d
template bindFirst(alias F, Args...)
{
   // this doesn't work
   // alias bindFirst(Args2...) = F!(Args, Args2);
   // but this does
   auto bindFirst(Args2...)(Args2 args2) { return 
F!(Args)(args2); }

}

alias bf = bindFirst!(foo, int);
bf("hello", 5); // ok
```

It would be nice if the alias worked, but I don't know what's 
involved to make IFTI work there. I know I can alter foo to be a 
template within a template. Perhaps that's the right answer. 
However, this doesn't help for functions already written that I 
can't alter.


Any ideas on how to solve this? I know my function solution is 
not very flexible...


-Steve


Re: DUB "Error: only one `main` allowed."

2021-08-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/11/21 5:31 AM, tastyminerals wrote:

I would like to trigger tests in a simple dub project.

```
source/my_script.d
dub.json
```

Here is a dub config:
```json
{
     "targetPath": "build",
 "targetType": "executable",
 "sourcePaths": ["source"],
 "name": "my_script",
 "buildTypes": {
     "release": {
     "buildOptions": [
     "releaseMode",
     "inline",
     "optimize"
     ]
     },
     "tests": {
     "buildOptions": [
     "unittests"
     ]
     }
 }
}

```
The project builds but when I attempt to run `dub test`, I get

```
.dub/code/my_script-test-application-unittest-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.26.0-8A5B544D5AC6B47B68DE875ACB4BA60E_dub_test_root.d(9,12): 
Error: only one `main` allowed. Previously found `main` at 
source/my_script.d(131,6)

```

How can one run tests with dub?



`dub -b unittest` should work (you don't need the extra build type stuff)

dub test does something funky -- it removes the *whole module* where 
your main function is (if you identify it, or if it's `app.d`) and then 
builds its own main module. Why does it do this? Legacy reasons, the 
runtime used to run main after running unittests, which dub didn't want 
to do. It also is useful on a library where there is no main function.


However, dub with a build type of `unittest` just enables the unittest 
switch, and builds all your stuff as normal.


-Steve


Re: How Add Local modules mymodule.d using DUB?

2021-08-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/9/21 12:32 PM, Marcone wrote:

My main program need import a local module called mymodule.d.
How can I add this module using DUB? Thank you.


You mean how to add a local project (that isn't on code.dlang.org)?

`dub add-local .` inside the project directory.

I don't think you can add a file directly without a project, but possibly.

-Steve


Re: best/proper way to declare constants ?

2021-08-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/5/21 11:09 AM, someone wrote:

On Thursday, 5 August 2021 at 10:28:00 UTC, Steven Schveighoffer wrote:

H.S. Teoh, I know you know better than this ;) None of this is 
necessary, you just need `rtValue` for both runtime and CTFE (and 
compile time parameters)!


Now, the original question is about *associative arrays*, which are a 
different animal. Those, you actually have to initialize using a 
static constructor, and does indeed need both an enum and a static 
immutable, as CTFE currently does not understand runtime AAs. This is 
a huge issue since you do need silly things like the `if(__ctfe)` 
statement you wrote, and keep an enum handy for those cases which is 
identical to the static immutable. We really need to fix this.


When you say "We really need to fix this" you mean that *eventually* 
associative-arrays will be available at compile-time ?


I mean eventually AAs that are reasonably available at compile time, 
even though the structure is determined by the runtime, should be 
available at compile time. This allows them to be as usable with static 
immutable as regular arrays (and just about any other struct) are.


Right now, AA's implementation is completely opaque via extern(C) 
function prototypes implemented in the runtime, so the compiler doesn't 
know how to make one.


-Steve


Re: best/proper way to declare constants ?

2021-08-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/4/21 11:20 PM, H. S. Teoh wrote:

On Thu, Aug 05, 2021 at 01:39:42AM +, someone via Digitalmars-d-learn wrote:
[...]

What happens in the following case ?

public immutable enum gudtLocations = [
r"BUE"d : structureLocation(r"arg"d, r"Buenos Aires"d, r"ART"d),
r"GRU"d : structureLocation(r"bra"d, r"São Paulo"d, r"BRT"d),
r"HHN"d : structureLocation(r"deu"d, r"Frankfurt am Main"d, r"CET"d),
r"LHR"d : structureLocation(r"gbr"d, r"London"d, r"UTC"d),
r"NYC"d : structureLocation(r"usa"d, r"New York"d, r"EST"d)
];

This is something that I also need at compilation time.

[...]

If you need a constant array value both at compile-time and runtime, one
way to do it is to declare an enum that is used only by compile-time
code, and the same enum is used once to declare the runtime static
immutable.


A static immutable *array* is usable at compile time. No need for the enum.



Example:

enum ctValue = [ "my", "data", "here", ... ];

// Initialize this once with ctValue.
static immutable string[] rtValue = ctValue;

if (ctfe) {


`if(__ctfe) {`


// Compile-time: use ctValue
foreach (value; ctValue) {
...
}
} else {
// Runtime: use rtValue instead
foreach (value; rtValue) {
...
}
}

Just be sure you don't use ctValue during runtime, otherwise it will
incur an allocation per use.


H.S. Teoh, I know you know better than this ;) None of this is 
necessary, you just need `rtValue` for both runtime and CTFE (and 
compile time parameters)!


Now, the original question is about *associative arrays*, which are a 
different animal. Those, you actually have to initialize using a static 
constructor, and does indeed need both an enum and a static immutable, 
as CTFE currently does not understand runtime AAs. This is a huge issue 
since you do need silly things like the `if(__ctfe)` statement you 
wrote, and keep an enum handy for those cases which is identical to the 
static immutable. We really need to fix this.


-Steve


Re: __FILE__

2021-08-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/4/21 10:27 PM, Ali Çehreli wrote:
I wonder whether this feature is thanks to 'lazy' parameters, which are 
actually delegates.


No, the default parameters are used directly as if they were typed in at 
the call site (more or less, obviously the `__FILE__` example is weird).


So:

```d
writeln(foo());
```

is just like you did:

```d
writeln(foo(bar()));
```

There are no lazy parameters involved.

-Steve


Re: best/proper way to declare constants ?

2021-08-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/4/21 10:27 PM, someone wrote:

On Thursday, 5 August 2021 at 02:06:13 UTC, Steven Schveighoffer wrote:

On 8/4/21 9:14 PM, H. S. Teoh wrote:

Unless you have a specific reason to, avoid using `enum` with string and
array literals, because they will trigger a memory allocation *at every
single reference to them*, which is probably not what you want.


Just want to chime in and say this is NOT true for string literals. 
Only array literals.


OK. Not for arrays then ... but for string literals ? which one then ?

static immutable string fileName = "list.txt";

vs

enum fileName = "list.txt";


The main difference between enums and static immutable is that the 
latter has an address at runtime. You cannot take the address of an enum 
(which only exists at compile time). You can think of an enum to be a 
substitute for typing out that expression directly. For array literals, 
this means, do a new allocation.


However, a string literal is a special case of an array which does NOT 
allocate -- it puts the string data into the read-only segment, and the 
literal references that data, which is why string enums do not allocate 
when used.


So the answer is, depends on what you are going to do with the data. 
There are use cases for both. If you just want an alias to represent the 
literal, I'd say use enum, it should work fine.


Off the top of my head for strings:

1. A static immutable loses its "C string compatibility", whereas an 
enum does not.
2. A static immutable can be passed as an alias to a template, and the 
template mangle only involves the variable name, whereas passing an enum 
will use the string *contents* for the template mangle. This can be a 
huge difference for symbol sizes.
3. A static immutable can be used as an argument to a reference 
parameter, an enum cannot.
4. A static immutable will consume space in your executable even if 
never used, an enum will not.


-Steve


Re: __FILE__

2021-08-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/26/21 1:05 PM, Stefan Koch wrote:

On Monday, 26 July 2021 at 12:01:23 UTC, Adam D Ruppe wrote:

On Monday, 26 July 2021 at 11:43:56 UTC, workman wrote:

__FILE__[0..$]


Why do you have that [0..$] there? It is probably breaking the 
__FILE__ magic.


Correct.
The compiler has to evaluate the default argument as constant expression 
in order to use it as default value..


This is not true, you can use runtime calls as default values.

Therefore it evaluates (__FILE__)[0 ..$]you first eval __FILE__ at CTFE 
within the module you are defining the function in.

And then you slice it from zero to length.


This might be how it is implemented, but it shouldn't be. `__FILE__` 
should be usable inside any expression as a default value, which should 
expand to the call-site for the function (as usual).


But this has nothing to do with CTFE as far as I know.

-Steve


Re: best/proper way to declare constants ?

2021-08-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/4/21 9:14 PM, H. S. Teoh wrote:

Unless you have a specific reason to, avoid using `enum` with string and
array literals, because they will trigger a memory allocation *at every
single reference to them*, which is probably not what you want.


Just want to chime in and say this is NOT true for string literals. Only 
array literals.


-Steve


Re: __traits() to get parameter details only ? ... hasMember looks up everything within

2021-08-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/4/21 11:08 AM, someone wrote:

However, __traits(hasMember, ...) checks for the existence of anything 
labeled lstrCurrencyID within the class (eg: unrelated variables with 
same name; not gonna happen, but, I like to code it the right way); so, 
question is: is there any way to search the parameter declarations only ?


Have you looked at 
[std.traits](https://dlang.org/phobos/std_traits.html) at all? It does a 
lot of stuff, including giving you parameter names and types.


-Steve


Re: Two major problems with dub

2021-08-04 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/4/21 4:18 AM, evilrat wrote:

On Wednesday, 4 August 2021 at 07:21:56 UTC, Denis Feklushkin wrote:

On Sunday, 1 August 2021 at 17:37:01 UTC, evilrat wrote:

vibe-d - probably because it handles DB connection and/or keep things 
async way, sure you probably can do it with Phobos but it will be 
much more PITA and less performant


It is because Postgres provides JSON types


Than again like I said it is library author mistake, if only JSON is 
ever used then it should depend on vibe-d:data specifically and not the 
whole vibe-d thing.


He is the library author. And [that's exactly what he 
does](https://github.com/denizzzka/dpq2/blob/c1f1c7c26f7e6cac7a34778dc580c92d8dec013b/dub.json#L12).


Note that when you depend on a subpackage, it downloads the entire 
repository (it has to), but will only build the subpackage.


-Steve


Re: Two major problems with dub

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

On 8/1/21 11:38 AM, Alain De Vos wrote:

Dub has two big problems.
1. Unmaintained dub stuff.
2. Let's say you need bindings to postgresql library and you will see 
dub pulling in numerous of libraries, which have nothing at all to do 
with postgresql.
More like a framework stuff. This creates unneeded complexity, 
bloatware, dependency hell, maintainability, in my humble opinion. Dub 
should do one thing and do it good.

Feel free to elaborate.


My biggest pet peeve is when a library pulls in a unittest framework 
(which then might pull in all kinds of other things). I get it, and I 
get why it's needed as a non-optional dependency, but I have no 
intention on unittesting the library, I just want to use it. It's a 
shame to pull in everything that it needs because of that.


I recently added the 
[dateparser](https://code.dlang.org/packages/dateparser) project as a 
library. I found it was pulling in emsi-container, so it could have an 
array container ([one line of 
code](https://github.com/JackStouffer/date-parser/blob/55e6218427974051b5179c98e0828b1d2a17629e/source/dateparser/package.d#L807)) 
that enables use of stdx.allocator. Ironically, the default (and all I 
cared about) is using the GC allocator. I wish there was a way to make 
this dependency optional. If more dub projects used optional 
dependencies, that would be nice.


Given the way D works, and often template-heavy coding styles, I think 
it's going to be hard to do this correctly, without careful attention 
and lots of `version(has_xxx)` conditionals.


-Steve


Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?

2021-07-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/23/21 3:30 PM, apz28 wrote:

On Friday, 23 July 2021 at 18:44:47 UTC, Steven Schveighoffer wrote:

On 7/22/21 7:43 PM, apz28 wrote:



In any case, it's possible that fbConnection being null does not mean 
a null dereference, but I'd have to see the class itself. I'm 
surprised if you don't get a null dereference in non-release mode, 
unless this code is never actually called.




The -debug build with passing unit-tests so no problem there.
The -release build is having problem. After make change to accommodate 
it, it takes forever to build. I started it yesterday 11AM and it is 
still compiling now (more than a day already.) It takes a full 100% core 
and peek memory usage is 2.2GB. The hard-drive is SSD


That is a separate problem. That build is hung, and you likely have 
found a bug in the compiler. I have never seen a build last more than a 
few minutes at the most.


If the code you posted is not crashing with a segfault, then it's 
possible there is a code generation issue. I still believe you have your 
check backwards.


-Steve


  1   2   3   4   5   6   7   8   9   10   >