July 26, 2019
On Friday, 26 July 2019 at 13:02:21 UTC, FeepingCreature wrote:
> I would like to voice a very enthusiastic recommendation for Dustmite for reducing programs to tests. Since it just requires a pass/fail test, it's easy to write a shellscript that checks that DMD's output matches a specific pattern, such as "COMPILE:.*".

Honestly, hot take/opinion time here. But every time I hear someone say "Dustmite" my immediate reaction is "Well I guess D isn't ready for production code."

Let's have a for real example.

I have a static assert in my receive function. If it detects that you've defined a message but haven't provided an implementation for receiving that message, it'll helpfully tell you exactly what you need to do.

For the sake of my C# bindings, I'm doing a mixin within a mixin to generate correct message responses for an entire class of messages dealing with creating/syncing/deleting objects.

Inside these functions, of course I write errors. Outside of {} braces, I almost never write any given line of code once. Things I haven't imported, typos, whatever. Nothing ever compiles first time.

So I hit compile expecting to see what kind of problems are going on now.

My static assert fires saying that this message isn't defined, compile stops dead in its tracks.

I sit there going "what the Zod" for twenty minutes, double checking template definitions, rewriting template declarations, before I finally decide to go in to my send function and comment out the static assert and just let the compiler error on the receive call.

Errors start showing up as normal in my templated functions.

So what's going on here? Internally, the compiler knows my templated function won't compile. It knows there's an error. It knows the symbol can't be defined. But instead of giving me the errors for what's going on there first, it sees my static assert and jumps off a rather tall cliff taking everything it knows with it.

Now, I could Dustmite my project. Which currently sits at 73 .d files and 6,447 lines of D code and growing. (There's more C# at the moment, but I autogenerate a bunch of it and depenency properties are responsible for a ton of pointless bloat - but that's a digression.) Throw in Binderoo as well since I can't use C# without Binderoo giving me bindings for my code. Copy it all off somewhere I won't touch and let it run for potentially days finding a minimal reproducible set.

Or maybe I could spend the time to isolate and work out what makes the compiler do these weird things.

Or I could do what I do daily in a production environment - fix or workaround the bug and get on trying to meet a deadline.

I'll take door number three thanks. That potential customer isn't going to care how many bug reports I write, especially since I inevitably come across something a couple of hours later that should be Dustmited... Dustmote... Dusted. Whatever. I don't have that much CPU power to spare.

Now.

I know that's also a counter-productive viewpoint to have. "I got a bug!" Great, submit a bug report with a reproducible case. "I don't have the time!"

Who else but me, right?

But the overall point I started making at the start of this post is that door number three point. Get D in to a production environment, people aren't going to engage in jolly community co-operation. They want to get their job done, meet their goals/targets, get paid, eat, and generally just complain to their co-workers about the latest weird <yeah, imagine I broke the white-collar forum protocol here> that D is doing. Like every other colleague you've ever known using every other language you've ever used professionally.

Wrapping up. Short of ye olde corporate "sign this NDA and get the keys to my codebase" approach to look at, I'm not sure what the middle ground is.
July 26, 2019
On Friday, 26 July 2019 at 15:02:43 UTC, Ethan wrote:
> Now, I could Dustmite my project. Which currently sits at 73 .d files and 6,447 lines of D code and growing. (There's more C# at the moment, but I autogenerate a bunch of it and depenency properties are responsible for a ton of pointless bloat - but that's a digression.) Throw in Binderoo as well since I can't use C# without Binderoo giving me bindings for my code. Copy it all off somewhere I won't touch and let it run for potentially days finding a minimal reproducible set.
>
> Or maybe I could spend the time to isolate and work out what makes the compiler do these weird things.
>
> Or I could do what I do daily in a production environment - fix or workaround the bug and get on trying to meet a deadline.
>

Fair enough. When I hit a situation like that, I do take the time to dustmite things down and file a bug (and PR, if possible), but I am very much blessed to have a boss who understands that if you hit a bug, you can't really expect things to improve if you don't file a report, and that my coworkers have patience for me to wander off on a bug filing/fixing tangent.

On the other hand, a lot of our longstanding pain points with D have actually gotten fixed, and none of that would have happened if there hadn't been bug reports. If you're long-term committed to a language, chances are that bug will show up again and waste hours of your time again. At some point it becomes cheaper to just file and fix it, instead of spending weeks of a new coworker's onboarding time getting them up to speed on all the D issues you've learnt to sidestep.

And no, this does not exactly say good things about D for production use...
July 27, 2019
On Friday, 26 July 2019 at 15:02:43 UTC, Ethan wrote:
> I have a static assert in my receive function. If it detects that you've defined a message but haven't provided an implementation for receiving that message, it'll helpfully tell you exactly what you need to do.
>
> comment out the static assert and just let the compiler error on the receive call.

Isn't your complaint that the assert is not helpful? If it was helpful and told exactly what you need to do, why do you need to remove it and debug?
July 27, 2019
On Saturday, 27 July 2019 at 09:14:54 UTC, Kagamin wrote:
> Isn't your complaint that the assert is not helpful?

No, the complaint is that DMD withheld error information in favor of my static assert.

> If it was helpful and told exactly what you need to do, why do you need to remove it and debug?

Because DMD withheld error information in favor of my static assert.

So. Since I clearly didn't contextualise this properly.

The static assert itself is in a mixin template. It is used in four objects currently - two different kinds of clients, and the server receivers that limit what they can do.

This is why the static assert was added in the first place - an error would happen, DMD would report the error location as being inside a mixin without context as to where the mixin was invoked, and I'd be left wondering which part of my code I overlooked this time.

Messages themselves are implemented in a mixin template. Mix them all in to the same class.

Normally, these messages will compile, throw the error, and then the static assert will tell you the handy information.

In this case, I wasn't getting the error messages and no idea of why the static assert was firing.

This just plain appears to be a static assert problem in general. Probably by design, except the spec doesn't mention that static assert is dependent on scope resolution order. Here's an example without templates that illustrates what I'm referring to. Move the static assert inside main() and you get the behavior I was expecting.

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

--

void broken()
{
    doesntexist();
}

int main( string[] args )
{
    broken();
}

static assert( false, "so here's a static assert" );
July 27, 2019
On Saturday, 27 July 2019 at 11:24:11 UTC, Ethan wrote:
> https://run.dlang.io/is/rjTRks
>
> --
>
> void broken()
> {
>     doesntexist();
> }
>
> int main( string[] args )
> {
>     broken();
> }
>
> static assert( false, "so here's a static assert" );

Again, in this example the compiler does provide context that assert fails at line 11. Function bodies are compiled at a later stage and it doesn't make sense to compile them if top level declarations failed to compile, if `doesntexist` only failed to compile and its every usage is reported as an error, it will be a very big amount of errors, which isn't helpful.
July 27, 2019
On Saturday, 27 July 2019 at 16:36:35 UTC, Kagamin wrote:
> Again, in this example the compiler does provide context that assert fails at line 11. Function bodies are compiled at a later stage and it doesn't make sense to compile them if top level declarations failed to compile

Your definition of context is incomplete.

I cannot think of a single programmer that wants to hit compile every time they fix one single compiler error just to find another single compile error.

Stopping at one static assert is undesired behavior in a production environment.

If this behavior is by design, it's terrible design.
July 27, 2019
When a function is compiled in incorrect environment it's likely to report induced errors, and those are very confusing. Do programmers want to hunt for induced errors? When the compiler is invoked in console and first prints the relevant error and then lots of induced errors, they will scroll the relevant error out of sight, the fact that stacks are printed inside out is a little unwieldy too.
July 27, 2019
On Saturday, 27 July 2019 at 18:59:20 UTC, Kagamin wrote:
> Something

Is that proving my point? I think it is. It appears you implied a programmer will hunt for the correct error message given a complete output. Which the current static assert functionality is not making possible.

Either that or you're arguing that reducing the context of an error message is helpful to someone. Which, hey, I've got news for you.
July 27, 2019
On Saturday, 27 July 2019 at 16:59:36 UTC, Ethan wrote:
> Stopping at one static assert is undesired behavior in a production environment.

If continuing is desired, would a `static if` combined with `pragma (msg, ...)` not be more appropriate than `static assert`? This can probably go into a ct function like `static_check`.

Bastiaan.

July 27, 2019
On Saturday, 27 July 2019 at 22:19:20 UTC, Bastiaan Veelo wrote:
> If continuing is desired, would a `static if` combined with `pragma (msg, ...)` not be more appropriate than `static assert`? This can probably go into a ct function like `static_check`.
>
> Bastiaan.

I was considering making that point myself. The static assert here is kinda useless, a pragma( msg ) won't stop compilation.

This is in that weird <non-PC word> area that people keep bringing up. The recommended course of development with templates is to static assert with your own handy error message. The reality is that you lose vital information about why that template is not instantiating unless you litter your code with static ifs and pragma( msg )s.