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


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/22/21 7:43 PM, apz28 wrote:

FbConnection is a class, FbXdrReader is a struct and for this call, 
response.data is not null & its' length will be greater than zero and 
FbConnection is not being used. So why DMD try to evaluate at compiled 
time hence error

1. Should not evaluate at compile time for this function call/construct
2. The error message is missing proper line # or nothing related to the 
module displayed in error message


https://github.com/apz28/dlang/blob/main/source/pham/db/db_fbbuffer.d#L527



I have a feeling that line is backwards.

It says: if the buffer has length, ignore it and use the connection, 
otherwise use the (empty) buffer data.


So perhaps this is actually a real error that is being flagged (because 
it's inlined)?


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.


-Steve


Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?

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

On 7/22/21 2:38 PM, apz28 wrote:

On Wednesday, 21 July 2021 at 20:39:54 UTC, Dukc wrote:

On Wednesday, 21 July 2021 at 14:15:51 UTC, Steven Schveighoffer wrote:
2. It's hard for me to see where the null dereference would be in 
that function (the `bool` implementation is pretty simple).




DMD complains about dereferences in three different lines. I suspect 
it's `this` reference that is `null`.


Look like DMD has some bug. If I changed this line 
https://github.com/apz28/dlang/blob/02989b94bfe306d723f2780e010c61f71f873cbe/source/pham/db/db_fbdatabase.d#L148 



from: auto reader = FbXdrReader(null, response.data);
to: auto reader = FbXdrReader(fbConnection, response.data);

then the error go away. FbXdrReader constructor allows to accept null 
for that parameter. Is it "safe" means not allow to pass null?


I don't know what an FbConnection is, but it looks like you call 
something on it. Your code is immense, and github search really *really* 
sucks. So I can't get better information. But if it's a class, and that 
is a normal member, it is indeed dereferencing a null pointer.


-Steve


Re: associative array with Parallel

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

On 7/22/21 1:46 AM, seany wrote:

Consider :

     int [] ii;
     foreach(i,dummy; parallel(somearray)) {
   ii ~= somefunc(dummy);
     }


This is not safe, because all threads are accessing the same array and 
trying to add values and leading to collision.


Correct. You must synchronize on ii.




But :

     int [] ii;
     ii.length = somearray.length;
     foreach(i,dummy; parallel(somearray)) {
   ii[i] ~= somefunc(dummy);
     }


This is safe. In this case, threads are accessing an unique memory 
location each.


This isn't valid code, because you can't append to an integer. Though I 
think I know what you meant. Is it thread-safe (assuming the array 
elements are appendable)? I think so, but I'd have to see a working example.




But what about this :

     int [ string ] ii;
     ii.length = somearray.length;
     foreach(i,dummy; parallel(somearray)) {
   string j = generateUniqueString(i);
   ii[j] ~= somefunc(dummy);
     }


Is this also guaranteed thread safe?


First, this also isn't valid code. You can't set the length of an AA. 
But I'm assuming that length setting is really a placeholder for 
initialization (in your real code). Also, again, you cannot append to an 
integer.


Second, as long as you don't modify the AA *structure*, you can parallel 
with it. In this case, you are generating some string, and appending to 
that. I don't know what your `generateUniqueString` is doing, nor do I 
know what's actually stored as keys in the AA as your initialization 
code is hidden.


If every `j` is guaranteed to already exist as a key in the AA, and the 
code is made to be valid, then I think it is thread-safe.


If any access with a key `j` is inserting a new AA bucket, it is *not* 
thread-safe.


However, this is a tall order, and highly depends on your code. The 
compiler cannot help you here.


In my 5 runs, I did not see any problems, but I'd like to confirm. Thank 
you.


Testing 5 times is not a substitute for proving the thread safety.

I have learned one thing long ago about threads and race conditions. 
Just don't do it. Ever. Even if you test 1 times, and it doesn't 
fail, it will eventually. I've had code that hit a race condition after 
2 weeks of running flat-out. Was one of the hardest things I ever had to 
debug.


-Steve


Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?

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

On 7/21/21 7:56 AM, apz28 wrote:

On Wednesday, 21 July 2021 at 11:52:39 UTC, apz28 wrote:

On Wednesday, 21 July 2021 at 04:52:44 UTC, Mathias LANG wrote:



It seems the compiler is doing extra analysis and seeing that a null 
pointer is being dereferenced. Can you provide the code for 
"pham\db\db_skdatabase.d" at L138 through 140 ?


    ```d
    package(pham.db):  // Line# 133
    final DbReadBuffer acquireSocketReadBuffer(size_t capacity = 
DbDefaultSize.socketReadBufferLength) nothrow @safe

    {
    version (TraceFunction) dgFunctionTrace();

    if (_socketReadBuffer is null)
    _socketReadBuffer = createSocketReadBuffer(capacity);
    return _socketReadBuffer;
    }
    ```


The entire codes is available from github
https://github.com/apz28/dlang/blob/main/source/pham/db/db_skdatabase.d#L138 



1. That filename is totally wrong, or the function name is totally 
wrong. ddemangle says the function is `@safe bool[] 
pham.db.fbdatabase.FbArray.readArrayImpl!(bool).readArrayImpl(pham.db.database.DbNameColumn)` 
which seems to be located 
[here](https://github.com/apz28/dlang/blob/02989b94bfe306d723f2780e010c61f71f873cbe/source/pham/db/db_fbdatabase.d#L142) 
But the line numbers also don't match. maybe an inlining issue?


2. It's hard for me to see where the null dereference would be in that 
function (the `bool` implementation is pretty simple).


-Steve


Re: betterC shared static ctor

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

On 7/21/21 5:07 AM, vit wrote:


Thanks, it works, but now I have different problem.
I need call static method for all instantions of template struct from 
`crt_constructor`.

Is there way to iterate over all instantions of template?


Not unless you register them somehow upon instantiation.

Or (I think) you can implement the constructor as a static method, and 
tag it with `pragma(crt_constructor)`. Then it gets added when instantiated.


-Steve


Re: How to parse a json node that contains children of different types?

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

On 7/20/21 11:00 PM, Mathias LANG wrote:

But if you take a step back, I think you might find this solution is far 
from ideal.
Having worked on a JSON library myself, I can tell you they are all 
implemented with a tagged union. And converting a tagged union to a 
tagged union is no improvement.


Not [jsoniopipe](https://github.com/schveiguy/jsoniopipe). In that case, 
you could use a specialized type with a `fromJSON` static member to do 
whatever you wanted.


-Steve


Re: Yet another parallel foreach + continue question

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

On 7/19/21 10:58 PM, H. S. Teoh wrote:


I didn't check the implementation to verify this, but I'm pretty sure
`break`, `continue`, etc., in the parallel foreach body does not change
which iteration gets run or not.


`break` should be undefined behavior (it is impossible to know which 
loops have already executed by that point). `continue` should be fine.


Noted in the 
[docs](https://dlang.org/phobos/std_parallelism.html#.TaskPool.parallel):


	Breaking from a parallel foreach loop via a break, labeled break, 
labeled continue, return or goto statement throws a ParallelForeachError.


I would say `continue` is ok (probably just implemented as an early 
return), but all those others are going to throw an error (unrecoverable).


-Steve


Re: How to create friends of a class at compile time?

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

On 7/15/21 1:43 PM, Tejas wrote:

How do you write the equivalent of that in D? Is the answer still the 
same? Manually keep it in the same module, or is there a programmatic 
way of converting this to D?


Functions in the same module can access `private` members. Functions in 
the same package (or in whatever package you specify) can access 
`package` members. That is how D does "friends".


So the answer to your question depends on how the C++ code is organized.

It's always possible that something in C++ here is not translatable into 
D, but most likely can be redesigned (and likely better designed).


-Steve


Re: Manipulate and parse jasonb object in timescaledb(postgresql)

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

On 7/14/21 9:00 AM, Alain De Vos wrote:
When I read a record out of the database I receive a jsonb datatatype as 
a string.
How do I convert this string into a json object and parse and manipulate 
it?


Isn't jsonb just a storage assumption for the database (so it can do 
efficient indexing/searches)? When you get the data back, I would think 
it's just json data you can parse.


I don't have experience with it, but I can't imagine a portable psql 
library that actually implements whatever binary storage format is being 
used inside the DB.


-Steve


Re: Can I get the time "Duration" in "nsecs" acurracy?

2021-07-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/9/21 5:13 PM, rempas wrote:

On Friday, 9 July 2021 at 20:54:21 UTC, Paul Backus wrote:

On Friday, 9 July 2021 at 20:43:48 UTC, rempas wrote:
I'm reading the library reference for 
[core.time](https://dlang.org/phobos/core_time.html#Duration) and It 
says that the duration is taken in "hnsecs" and I cannot understand 
if we can change that and choose the precision. Does anyone know if 
we can do that?


It is stored internally in "hnsecs", but you can convert it to other 
units using the `total` method [1]; for example, 
`myDuration.total!"nsecs"`.


[1] https://dlang.org/phobos/core_time.html#.Duration.total


It doesn't work for me. I have the following code:

```
MonoTime start = MonoTime.currTime();
// Doing stuff
MonoTime end = MonoTime.currTime();
Duration dur = end - start;
dur = dur.total!"nsecs";
```

and I get the following error message:

"Error: cannot implicitly convert expression \`dur.total()\` of type 
\`long\` to \`Duration`"


BTW `Duration` is truncating here. `MonoTime` stores its values in 
implementation-defined ticks, which can be nanoseconds or any other 
thing that the specific clock uses. Whereas `Duration` uses strictly hnsecs.


If you want to get sub-hnsec resolution, use the `ticks` member of 
`MonoTime` and `ticksPerSecond` and do the math for the units.


See the warning 
[here](https://dlang.org/phobos/core_time.html#.MonoTimeImpl.opBinary).


-Steve


Re: mixin template's alias parameter ... ignored ?

2021-07-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/11/21 8:49 AM, Adam D Ruppe wrote:

On Sunday, 11 July 2021 at 05:20:49 UTC, someone wrote:

```d
mixin template templateUGC (
   typeStringUTF,
   alias lstrStructureID
   ) {

   public struct lstrStructureID {

  typeStringUTF whatever;

   }



This creates a struct with teh literal name `lstrStructureID`. Just like 
any other name. So it is NOT the value of the variable.



```d
   public struct mixin(lstrStructureID) { ... }
```

because the argument seems to require a complete statement.


Indeed, you'd have to mixin the whole thing like

mixin("public struct " ~ lstrStructureId ~ " { ... } ");


when I've done this kind of stuff, what I usually do is:

```d
struct Thing {
  ... // actual struct
}

mixin("alias ", lstrStructureID, " = Thing;");
```

the downside is that the actual struct name symbol will be `Thing`, or 
whatever you called it. But at least you are not writing lots of code 
using mixins.


-Steve


Re: assert(false) and GC

2021-07-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/10/21 12:32 PM, Mathias LANG wrote:

On Saturday, 10 July 2021 at 01:38:06 UTC, russhy wrote:

On Saturday, 10 July 2021 at 01:23:26 UTC, Steven Schveighoffer wrote:


I think it's the throwing/catching of the `Throwable` that is 
allocating. But I don't know from where the allocation happens.




i think you are right


Try to use `@nogc` instead, it'll show you it does not allocate.
A caveat though: A failing assert used to allocate before v2.097.0 (the 
latest version), it does not anymore.


However, as your test captures all GC allocation, it likely triggers 
while the runtime is initializing.


No, because if you remove the assert, and just include the override of 
gc functions, nothing triggers. I can't remember which release, but the 
runtime has been changed to not use the GC until the application needs it.


The assert is triggering the GC, either on the throw or the catch (i.e. 
printing out the stack trace).


I tend to think the latter, but hard to prove with this simple test.

If you want to know where it is, just debug it and break in the GC 
allocation function.


-Steve


Re: assert(false) and GC

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

On 7/9/21 8:44 PM, russhy wrote:

On Friday, 9 July 2021 at 23:34:25 UTC, Ali Çehreli wrote:

On 7/9/21 4:12 PM, russhy wrote:

>> One way of forcing compile-time evaluation in D is to define
an enum
>> (which means "manifest constant" in that use).

That's all I meant. It was a general comment.

> this is very bad, assert are good because they are one liner,
making it
> 2 line to avoid GC is just poor design, compiler should be
smarter

There must be a misunderstanding. The one-liner does not allocate 
either (or @nogc is broken).




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

it allocates


That test is possibly showing the wrong thing. You are capturing all 
allocations, not just the concatenation.


Change the assert line to:

```d
string s = __FUNCTION__ ~ "This is an error message";
```

And no GC allocations occur. Even without optimizations turned on.

I think it's the throwing/catching of the `Throwable` that is 
allocating. But I don't know from where the allocation happens.


-Steve


Re: Can I get the time "Duration" in "nsecs" acurracy?

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

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

On 7/9/21 1:54 PM, Paul Backus wrote:

On Friday, 9 July 2021 at 20:43:48 UTC, rempas wrote:
I'm reading the library reference for 
[core.time](https://dlang.org/phobos/core_time.html#Duration) and It 
says that the duration is taken in "hnsecs" and I cannot understand 
if we can change that and choose the precision. Does anyone know if 
we can do that?


It is stored internally in "hnsecs", but you can convert it to other 
units using the `total` method [1]; for example, 
`myDuration.total!"nsecs"`.


[1] https://dlang.org/phobos/core_time.html#.Duration.total


Yes but the resolution seems not to be better than 100 nsecs. A quick 
research reveals a better resolution is not possible with common 
hardware on at least Linux.


The following program always prints multiples of 100 on my Mint OS:

import std.stdio;
import core.thread;
import std.datetime.stopwatch;

void main() {
   auto sw = StopWatch();
   sw.start();

   foreach (_; 0..10) {
     Thread.sleep(0.nsecs);
     writefln("%,s", sw.peek.total!"nsecs");
   }
}


You can get better than hnsecs resolution with `core.time.MonoTime`, 
which can support whatever the OS supports.


However, `Duration` and `SysTime` are stored in hnsecs for a very 
specific reason -- range. Simply put, if you have a 64-bit integer, and 
you picked nanoseconds as the unit, you can store only 585 years of 
range. 10 ns gives you 5850 years, and 100 ns gives you 58k years. That 
should be good enough for all but the most esoteric calculations (given 
that a `Duration` is signed, this gives a range of roughly -29k years to 
29k years).


Note also that hnsecs is the base unit for Windows high precision 
clocks, though their epoch is year 1600 instead of year 0.


-Steve


Re: Where is "open" in "core.sys.linux.unistd"?

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

On 7/9/21 11:31 AM, Dennis wrote:

On Friday, 9 July 2021 at 15:11:38 UTC, Steven Schveighoffer wrote:

But reading/writing, closing these file descriptors is always the same.


For sockets you'd typically use `recv` and `send` instead or `read` and 
`write` because the former give extra options and the latter don't work 
on Windows. But yeah, on Linux `read` and `write` should work 
universally among file descriptors.




I typically only use `send` and `recv` for for connectionless sockets. 
For TCP sockets, it's generally `read` and `write` for me (and it works 
fine).


Windows is a different story, they have different i/o routines for 
system calls (yes, there's the shims for Posix file descriptors, but I 
wouldn't use those anyway).


The larger point is that the reason `read`/`write` are separate from 
descriptor creation is because they are universal, while creation is not.


-Steve


Re: Where is "open" in "core.sys.linux.unistd"?

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

On 7/9/21 10:51 AM, rempas wrote:
The file can be found quickly 
[here](https://github.com/dlang/druntime/blob/master/src/core/sys/posix/unistd.d) 
or in your system if you want. Now the question is, why isn't there an 
"open" function for the equivalent system call? "close", "write", "read" 
etc. all exist. Anyone knows what's going on with open?


Because file descriptors are created in different ways.

For example, `open` exists for files 
[here](https://github.com/dlang/druntime/blob/master/src/core/sys/posix/fcntl.d)


But opening a socket is done via the `socket` system call 
[here](https://github.com/dlang/druntime/blob/master/src/core/sys/posix/sys/socket.d)


They don't take the same arguments (nor should they).

But reading/writing, closing these file descriptors is always the same.

-Steve


Re: to compose or hack?

2021-07-07 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/7/21 3:52 PM, Sebastiaan Koppe wrote:

On Wednesday, 7 July 2021 at 13:30:28 UTC, Steven Schveighoffer wrote:

On 7/7/21 5:54 AM, rassoc wrote:

On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote:
So I have this situation where I need to split a string, then where 
the splits are, insert a string to go between the elements making a 
new range, all without allocating (hopefully).




Without considering the more general case, isn't that just 
splitter-joiner?


No, splitter-joiner would make a range of characters, I want a range 
of strings.


Just lift each item in a range then:

```d
import std;

auto foo(string s, string sp, string j) @nogc {
  return s.splitter(sp).map!(i => only(i)).joiner(only(j));
}

void main() {
  foo("ab,cd,ef,gh", ",", "##").writeln; // => ["ab", "##", "cd", 
"##", "ef", "##", "gh"]

}
```


Thanks! This is exactly what I was reaching for. `only` is one of the 
coolest functions (I use it elsewhere too).


-Steve


Re: to compose or hack?

2021-07-07 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/7/21 5:54 AM, rassoc wrote:

On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote:
So I have this situation where I need to split a string, then where 
the splits are, insert a string to go between the elements making a 
new range, all without allocating (hopefully).




Without considering the more general case, isn't that just splitter-joiner?


No, splitter-joiner would make a range of characters, I want a range of 
strings.



```d
import std;

auto foo(string s, string sp, string j) @nogc {
 return s.splitter(sp).joiner(j);
}

void main() {
     foo("ab,cd,ef,gh", ",", "##").writeln; // => ab##cd##ef##gh
}
```


Using your example, the correct result should be `["ab", "##", "cd", 
"##", "ef", "##", "gh"]`




Interesting! Tried it myself, shame that this doesn't quite work:

```d
import std;

auto foo(R)(string s, string sp, R r) @nogc {
     return s.splitter(sp).zip(r)
     .map!(a => a.expand.only)
     .joiner.dropBackOne.joiner; // not bidirectional
}

void main() {
     foo("ab,cd,ef,gh", ",", ["##", "**"].cycle).writeln;
}
```


ooh, I like the zip/expand/only trick! I got this to work, and lol, I 
don't think I'd ever use this:


```d
auto interleave(R, U)(R src, U middles) if (isInputRange!R && is(U == 
ElementType!R))

{
return zip(StoppingPolicy.shortest, src, middles.repeat)
  .map!(e => only(e.expand))
  .joiner
  .slide(2)
  .frontTransversal;
}
```

Ironically, I think it would still run the splitting algorithm 2x, 
because `slide` has to store 2 copies of the source range. And it's not 
nogc either. Hm... I bet `dropBackOne` might actually be able to work on 
a forward range if it cached one element? But that might be iffy.


-Steve


Re: to compose or hack?

2021-07-07 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/6/21 11:42 PM, Jon Degenhardt wrote:

On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote:
This is pretty minimal, but does what I want it to do. Is it ready for 
inclusion in Phobos? Not by a longshot! A truly generic interleave 
would properly forward everything else that the range supports (like 
`length`, `save`, etc).


But it got me thinking, how often do people roll their own vs. trying 
to compose using existing Phobos nuggets? I found this pretty 
satisfying, even if I didn't test it to death and maybe I use it only 
in one place. Do you find it difficult to use Phobos in a lot of 
situations to compose your specialized ranges?


I try to compose using existing Phobos facilities, but don't hesitate to 
write my own ranges. The reasons are usually along the lines you describe.


For one, range creation is easy in D, consistent with the pro/con 
tradeoffs described in the thread/talk [Iterator and Ranges: Comparing 
C++ to D to 
Rust](https://forum.dlang.org/thread/diexjstekiyzgxlic...@forum.dlang.org). 
Another is that if application/task specific logic is involved, it is 
often simpler/faster to just incorporate it into the range rather than 
figure out how to factor it out of the more general range. Especially if 
the range is not going to be used much.


Yeah, I agree with all this. I do try to use existing ranges/algorithms 
as much as possible. But I find it awesome you can just whip up a quick 
shim range to get work done and not worry about making it perfect for 
general consumption. Kind of like a lambda range ;)


-Steve


to compose or hack?

2021-07-06 Thread Steven Schveighoffer via Digitalmars-d-learn
So I have this situation where I need to split a string, then where the 
splits are, insert a string to go between the elements making a new 
range, all without allocating (hopefully).


Looking around phobos I found inside the documentation of 
[roundRobin](https://dlang.org/phobos/std_range.html#.roundRobin) 
something that does *exactly* what I'm looking for.


Except... the provided `interleave` function iterates the original range 
twice, which means 2x the searching calls for splitter. Why does it do 
this? Because `roundRobin` will keep going as long as ANY range still 
has data left, so you need to make the "interleaving" range stop when 
the first one stops.


After struggling to think up ways to compose this (hm.., can  I make the 
ranges share a stopping point?) without the 2x penalty, I just decided 
to write my own interleave range which does exactly what I am looking for:


```d
auto interleave(R, U)(R src, U middles) if (isInputRange!R && is(U == 
ElementType!R))

{
static struct Result
{
R src;
U middles;
bool between = false;
auto front() {
assert(!empty);
return between ? middles : src.front;
}
void popFront() {
assert(!empty);
if(between)
between = false;
else
{
src.popFront;
between = true;
}
}
bool empty()
{
return src.empty;
}
}

return Result(src, middles);
}
```

This is pretty minimal, but does what I want it to do. Is it ready for 
inclusion in Phobos? Not by a longshot! A truly generic interleave would 
properly forward everything else that the range supports (like `length`, 
`save`, etc).


But it got me thinking, how often do people roll their own vs. trying to 
compose using existing Phobos nuggets? I found this pretty satisfying, 
even if I didn't test it to death and maybe I use it only in one place. 
Do you find it difficult to use Phobos in a lot of situations to compose 
your specialized ranges?


Oh, and if you do know of a better way to compose the range that doesn't 
require the double iteration, I'd be interested in seeing it.


-Steve


Re: How to disable assigning a value to a property?

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

On 7/6/21 9:27 AM, Jack Applegame wrote:

On Tuesday, 6 July 2021 at 12:33:20 UTC, Adam D Ruppe wrote:

The language always allows `a = b;` to be rewritten as `a(b);`.


And that's sad. It should happen for properties only.



Yes, I lament that there is no way to control how people call your 
function. It can result in surprising things, and it means as a library 
designer you have to consider this usage when picking names.


There are a few "draft" DIP proposals (under the old DIP system) here: 
https://wiki.dlang.org/DIPs


But I think the time of being able to make such a disruptive change has 
passed. For better or worse we have the half-implemented near-useless 
meaning of `@property`, and basically it's unneeded.


-Steve


Re: anonymous functions and scope(exit)

2021-07-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/3/21 4:08 PM, frame wrote:

On Saturday, 3 July 2021 at 17:39:18 UTC, Steven Schveighoffer wrote:

But in practice, the compiler does not have to clean up anything when 
an `Error` is thrown. Whether it does or not is defined by the 
implementation.


This should be really mentionend in the docs? "Guard", yeah...




Yeah, there isn't a good discussion of the differences between Error and 
Exception on that page.


-Steve


Re: anonymous functions and scope(exit)

2021-07-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/3/21 1:20 PM, Luis wrote:

This is intentional ?

```
     should(function void() {
     auto emptyStack = SimpleStack!int();
     scope(exit) emptyStack.free; // <= This is never called

     emptyStack.reserve(16);
     emptyStack.top;
     }).Throw!RangeError;
```

scope(exit) inside of a anonymous functions, it's never called.


In principle, it should technically be called.

But in practice, the compiler does not have to clean up anything when an 
`Error` is thrown. Whether it does or not is defined by the implementation.


However, it should *always* work if it's an `Exception` and not an `Error`.

```d

import std.stdio;

void main()
{
auto f = function void() {
scope(exit) writeln("hi");
throw new Exception("boo");
};

f();
}
```

prints "hi"

-Steve


Re: how much "real-life" code can be marked @safe ?

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

On 7/1/21 8:26 PM, someone wrote:

... just wondering:

I am writing pretty trivial code, nothing out of the ordinary, and 
attempted to check how much of it could be marked safe ...


It should be quite a bit.



- Lots of tiny common library functions are pretty easy

- Getter/Setter properties are easy too

- almost all this() constructors are a no-go providing you do something 
in-between with the parameters until you assign them back to the target 
variables; eg: you have a char parameter (that you need to do something 
with it) that needs to be assigned to a class/structure string member 
variable and then it needs a cast ... but no castings are allowed with 
@safe


This doesn't make a lot of sense, lots of constructors are safe.

And casting is OK as long as it's safe, including class downcasts.



But when you start attempting to declare @safe chunks of code that 
actually DO things ... well, it seems end-of-the-story.


This is why you encapsulate the unsafe parts in @trusted functions.

The classic example is the posix `read` and `write` functions. The 
function `int read(int fd, void *data, int len)` is not safe, nor can it 
be trusted. But a trusted wrapper is possible: `@trusted int 
readSafe(int fd, ubyte[] data)`. Now all of a sudden, safe functions 
have more utility.




Declaring @safe void() main() {...} as I was advised in some previous 
post (to avoid declaring @safe everywhere) is almost impossible unless 
you are doing the hello world app.


The point is to mark main @safe, and then fix whatever things that 
aren't safe that it calls to provide a safe interface.




I would love to hear how you, I mean the community, approach code 
safeness ?


Any function I want to make safe, I mark it as @safe. Then I fix the 
compiler complaints until it compiles (including functions that it 
calls), using as little @trusted code as possible.


-Steve


Re: Printing Tuple!(...)[] using for loop?

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

On 7/2/21 12:21 AM, Kirill wrote:
I have a `Tuple!(string, ..., string)[] data` that I would like to print 
out:

`a   b   c`
`1   2   3`
`4   5   6`

     Furthermore, I want to be able to print any N rows and M columns of 
that table. For instance:

     `b   c`
     `2   3`
     or
     `1   2   3`
     `4   5   6`

I am using for loops for that:

     // inside some function(rows, cols):
     immutable startFromRow = ...;
     immutable endWithRow = ...;
     immutable startFromCol = ...;
     immutable endWithCol = ...;

     // print data
     for(size_t i = startFromRow; i < endWithRow; i++) {
     for(size_t j = startFromCol; j < endWithCol; j++) {
     writef("%s", data[i][j]);
     }
     writef("\n");
     }

And the compiler puts out the following:
`Error: variable 'j' cannot be read at compile time`

I tried `data[i].expand[j]`, but the same error occurs anyway.

I have two questions:
1. How do I print the contents of a Tuple using for loops? Or any other 
method?

2. What am I missing? How does it actually work under the hood?


So a tuple is really like an unnamed group of variables.

A `Tuple!(int, int, int)` is really like three ints that are all 
separate variables. It's just that they are named via the group. It is 
NOT like an array, it's more like a struct with fields that have indexes 
instead of names.


In order to print them in a loop, based on *runtime* data, you need to 
bridge the gap between runtime and compile time. Why? Because a Tuple 
does not necessarily contain the same types for every value, so `tup[0]` 
might have a different type than `tup[1]`. Because D is strongly-typed, 
you need to access these with *compile-time* indexes, so it knows what 
type you are using.


Imagine you have a struct, and you want to use a runtime string to 
access a given field. This is essentially the same, except it's an index 
and not a name.


A typical way to bridge the gap is to use a switch to validate the 
runtime variable, and then use the compile-time equivalalent to actually 
get the data.


For example, you could write a function like:

```d
void printItem(Tuple!(...) vals, size_t index)
{
theswitch:
final switch(index)
{
   static foreach(ctIdx; 0 .. vals.length) {
case ctIdx: writeln(vals[ctIdx]);
break theswitch;
   }
}
}
```

Now, if you want to just print them in order, without any runtime 
details, you can just use foreach on a tuple and it works (the foreach 
variables are compile-time determined).


-Steve


Re: SegFault trying to chunk lazily joined ranges

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

On 7/1/21 10:56 AM, Keivan Shah wrote:

Using the handler I was able to get the stack trace and it seems that 
the segFault is caused by `joiner` trying to call `.save` on a null 
object leading to a `NullPointerError`. But I have not been able to 
debug it further. Mostly it seems that there is something wrong with my 
understanding of ranges or it could be a genuine bug in std.range.

Can anyone help me debug this piece of code?


Thanks for the detailed instructions, very easy to reproduce.

However, chunkBy is a hot mess, which probably has a bug in it 
somewhere. I don't exactly know where this is, but know that using 
objects for forward ranges is bound to result in some failures, simply 
because they are one of the only forward ranges that *requires* calling 
`.save`, and much code exists that forgets to do that.


I spent about 20 minutes trying to find this and can't see how `chunkBy` 
actually works in this case. I don't have any more time to spend on it, 
sorry.


I narrowed your code down to the minimal case that I could find that 
segfaults:



```d
ForwardRange!int[] listOfRanges = [iota(1).inputRangeObject];
auto lazyFlattenedRange = joiner(listOfRanges);
auto d2 = lazyFlattenedRange.chunkBy!(a => a);
while(!d2.empty)
d2.popFront;
```

I hope this helps someone narrow it down.

-Steve


Re: How to reset the website when the user leaves it, with vibe.d?

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

On 6/29/21 4:25 PM, vnr wrote:

Nevertheless, the problem persists and seems to be even deeper, indeed, 
my site is hosted on Heroku and I can see what a user who is on another 
machine has written (behavior I just found out). Fortunately, this 
little site is only for entertainment purposes, but it is a behavior 
that seems quite vicious.


If you want to access the code, it is on [this 
repository](https://github.com/noc-lang/playground) (it is just a 
playground for the language of a friend).




Has nothing to do with sessions, you are saving the text posted, and 
then making it the default text whenever the page is rendered.


[here](https://github.com/noc-lang/playground/blob/0ec136b385c9aff306e15947082210d3bc230d10/source/app.d#L68) 
is where you save the text. 
[here](https://github.com/noc-lang/playground/blob/0ec136b385c9aff306e15947082210d3bc230d10/source/app.d#L50-L52) 
you pass it to the template, and 
[here](https://github.com/noc-lang/playground/blob/d6551e8a5f90b8ebc1732c6dfb72ba61113887af/views/home.dt#L128) 
you render it as the child of the text area.


Just don't do that ;)

-Steve


Re: Wrap + add methods?

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

On 6/28/21 11:53 AM, Paul Backus wrote:

On Monday, 28 June 2021 at 15:17:34 UTC, Steven Schveighoffer wrote:
I have a situation where I want to wrap a certain type to add a few 
methods to that type.


UFCS is not an option, because the library that will use this type 
will not import the UFCS methods.


`std.typecons.Proxy` doesn't seem to wrap static methods, and besides, 
I want to return wrappers if the function being wrapped returns the 
same type (this is critical for stuff like `auto result = a + b`, I 
want the result to be the same wrapped type).


Are there any libraries that might do this (including Phobos)?


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

Doesn't do everything you're looking for, but you might find some useful 
tricks in the source.


Very neat! I think I can't use it, because I need to add static methods.

My particular use case is a translated database type. In this case, it's 
a fixed point currency, which is stored as an integer in the database, 
but translated to a D fixedpoint type.


To make it work with my DB library, I need to have a method `dbValue` 
which converts the D type into an appropriate D type that the database 
can utilize (long in this case), and a static method `fromDBValue` which 
goes the opposite direction.


For now, I've just hand implemented the needed functions. This includes 
forwarding constructors, operator overloads, opAssign, etc.


-Steve


Wrap + add methods?

2021-06-28 Thread Steven Schveighoffer via Digitalmars-d-learn
I have a situation where I want to wrap a certain type to add a few 
methods to that type.


UFCS is not an option, because the library that will use this type will 
not import the UFCS methods.


`std.typecons.Proxy` doesn't seem to wrap static methods, and besides, I 
want to return wrappers if the function being wrapped returns the same 
type (this is critical for stuff like `auto result = a + b`, I want the 
result to be the same wrapped type).


Are there any libraries that might do this (including Phobos)?

-Steve


Re: is it possible to sort a float range ?

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

On 6/23/21 7:07 PM, someone wrote:

On Wednesday, 23 June 2021 at 22:46:28 UTC, Steven Schveighoffer wrote:


Use the `release` method:

```d
return lnumRange.sort!(...).release;
```



Fantastic, issue solved, I previously used sort ascending even 
descending but first time on floats.


So I went and searched phobos docs:

auto release();
Releases the controlled range and returns it.

Not much clarification there.

Can you elaborate a bit if possible Steve ?


I think the purpose behind it is to say "here, now you have the original 
range back, so I won't guarantee it's sorted any more." I'm pretty sure 
it also clears out the source range in the sorted range, so you can no 
longer use the sortedness functions, but that's easily circumvented 
using `save`.


I can't really defend the purpose/implementation of `SortedRange`, it's 
something in Phobos that I've complained about extensively in the past.


-Steve


Re: Detect if a struct is a 3-float vector

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

On 6/23/21 6:36 PM, JN wrote:

I'm looking for a way to test a struct for these conditions:

1. has members named x, y and z
2. these members are floating point type

This works, but feels kinda verbose, is there some shorter way? Can I 
somehow avoid the hasMember/getMember calls?


```d
import std.traits;

struct Vector3f
{
     float x, y, z;
}

struct Vector2f
{
     float x, y;
}

struct Vector3i
{
     int x, y, z;
}

bool isVector3fType(T)()
{
     static if (__traits(hasMember, T, "x") && __traits(hasMember, T, 
"y") && __traits(hasMember, T, "z"))

     {
     static if (isFloatingPoint!(typeof(__traits(getMember, T, "x")))
     && isFloatingPoint!(typeof(__traits(getMember, T, "y")))&& 
isFloatingPoint!(typeof(__traits(getMember, T, "z" {

     return true;
     }
     }
     return false;
}

void main()
{
     static assert(isVector3fType!Vector3f);
     static assert(!isVector3fType!Vector2f);
     static assert(!isVector3fType!Vector3i);
}
```


Hm.. what about:

```d
enum isVector3fType(T) = FieldNameTuple!T.length == 3 &&
FieldNameTuple!T == AliasSeq!("x", "y", "z") &&
allSatisfy!(isFloatingPoint, Fields!T);
```

(the length thing was required, otherwise the thing complained for Vector2f)

-Steve


Re: is it possible to sort a float range ?

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

On 6/23/21 6:30 PM, Jordan Wilson wrote:

On Wednesday, 23 June 2021 at 19:53:24 UTC, someone wrote:

Please, look for the line marked +++

This is a structure with a public property returning a (still 
unsorted) range built on-the-fly from already-set properties, a basic 
range from a to z with n step where some specific values can be added 
in-between. The range is a float which I am currently using for 
currency (horrible) and later plan to move it to decimal 10 or the like.


[...]


```sort``` returns a ```SortedRange```, and I believe you wish to return 
a float. So you can do either ```return lnumRange.sort!(...).array;```, 
or you can do ```lnumRange.sort!(...); return lnumRange```.


Use the `release` method:

```d
return lnumRange.sort!(...).release;
```

-Steve


Re: how to filter associative arrays with foreach ?

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

On 6/21/21 5:00 PM, Elronnd wrote:

On Monday, 21 June 2021 at 03:59:10 UTC, someone wrote:
Is there a way to filter the collection at the foreach-level to avoid 
the inner if ?


Here's how I would do it:

foreach (k, v; coll) {
     if (k == unwanted) continue;
     ...
}

You still have an if, but the actual loop body doesn't have to be 
nested, so it's easy to follow the control flow.


Alternatively (if you're ok with this sort of thing):

foreach (k, v; coll) if (k != unwanted) {
}

It's actually visually shorter than doing the filter.

And the benefit to using the if statement over the filter wrapper is 
that the compiler has to do a lot less work.


-Steve


<    2   3   4   5   6   7   8   9   10   11   >