August 23, 2018
On Thursday, August 23, 2018 3:26:46 AM MDT rikki cattermole via Digitalmars-d wrote:
> > * Language complexity
> >
> > Raise your hand if you know how a class with both opApply and the get/next/end functions behaves when you pass it to foreach. How about a struct? Does it matter if it allows copying or not?
>
> get/next/end functions, what?

I'm sure that he meant front, popFront, and empty. And yes, the fact that we have both opApply (the D1 solution for supporting foreach) and ranges (the D2 solution for foreach) definitely complicates things. Those two features do theoretically interact properly, because work was done several years ago to ensure that they did, but while they may interact properly from a technical standpoint, it's a mess from a social standpoint. I'm sure that some of the folks here could correctly answer whether foreach or the range API wins with foreach, but it's really not the sort of thing that the average D programmer is going to know, and while IIRC, there is very good reasoning as to which one wins, it's not immediately obvious to most folks. I _think_ that it's opApply that wins, but I'd have to either look it up or test it, and while I certainly don't know everything there is to know about D, given how much I've been involved with D, if I don't know something about it, the odds are pretty good that a lot of D programmers don't.

D does have a problem in general of having a lot of great features that work really well in isolation but don't necessarily work well in concert (and it doesn't help that some features have really never been properly finished). And frequently, the answer that folks go with is to simply not use sections of the language (e.g. it's _very_ common for folks to just give up on a lot of attributes like pure, nothrow, or @safe). A number of the issues do get worked out over time, but not all of them do, and sometimes the solutions cause a lot of problems. For instance, DIP 1000 may end up being great for @safe and will help solve certain issues, but it results in yet another attribute that has to be pasted all over your code and which most folks simply won't use. So, it's helping to fix a real problem, but is it making things better overall? I don't know.

And while I definitely think that D is easier to understand than C++ (in spite of the increase in D's complexity over time), it's also very much true that D continues to get more and more complicated as we add more stuff. Generally, each solution is solving a real problem, and at least some of time, the solution actually interacts quite well with the rest of the language, but it all adds up. And honestly, I don't think that there's a real solution to that. Languages pretty much always get more complicated over time, and unless we're willing to get rid of more stuff, it's guaranteed to just become more complicated over time rather than less.

D definitely improves over time, but certain classes of issues just never seem to be fixed for some reason (e.g. the issue with RAII and destructors really should have been fixed ages ago), and some of the major design decisions don't get fully sorted out for years, because they're not a high enough priority (e.g. shared). I don't really agree that D is in much danger of dying at this point, but I completely agree that we as a group are not doing a good enough job getting some of the key things done (much of which comes down to an issue of manpower, though some of it is also likely due to organizational issues).

- Jonathan M Davis



August 23, 2018
On Thursday, 23 August 2018 at 10:41:03 UTC, Jonathan M Davis wrote:

> Languages pretty much always get more complicated over time, and unless we're willing to get rid of more stuff, it's guaranteed to just become more complicated over time rather than less.

"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away." -- Antoine de Saint-Exupery

I think that's actually a mistranslation from what he actually said, but it's still quite good.

I think that's a important point of focus.  We should be trying to get rid of stuff.  It's one of the reasons I've been trying to move forward on some of the deprecations.  Once the decision to deprecate is made it takes at least 2 years to get it done.  The longer we wait, the longer we have to carry its baggage and risk its poor interaction with new features.

It's a good question to ask:  What can we get rid of?

I know it's radical, but I'd like to see if we could enhance structs a little and get rid of classes and interfaces.  See https://theartofmachinery.com/2018/08/13/inheritance_and_polymorphism_2.html for what I mean.

Mike

August 23, 2018
On 8/23/2018 2:09 AM, Shachar Shemesh wrote:
> On 23/08/18 09:58, Joakim wrote:
>> Because you've not listed any here, which makes you no better than some noob
> 
> Here's one: the forum does not respond well to criticism.

Not sure what you mean by that.


> * Features not playing well together.
> 
> Despite what Joakim seems to think, I've actually brought up an example in this thread. Here is another one:
> 
> functions may be @safe, nothrow, @nogc, pure. If it's a method it might also be const/inout/immutable, static. The number of libraries that support all combinations is exactly zero (e.g. - when passing a delegate in).

If, for example, a library functions allocates with the gc, then it can't work with @nogc code. But still, fair enough - if there are combinations which should work, but do not, please submit bug reports. If you have already, is there a list of them?


> * Language complexity
> 
> Raise your hand if you know how a class with both opApply and the get/next/end functions behaves when you pass it to foreach.
> How about a struct?

I presume you meant empty/front/popFront.

This is in the language spec:

https://dlang.org/spec/statement.html#foreach-with-ranges

"If the aggregate expression is a struct or class object, but the opApply for foreach, or opApplyReverse foreach_reverse do not exist, then iteration over struct and class objects can be done with range primitives."

This was done for backward compatibility, since empty/front/popFront came later. I actually tried to deprecate opApply at one point, but that would have broken too much existing code. But I'm puzzled why one would write a struct with both iteration mechanisms.


> Does it matter if it allows copying or not?

For the preference for opApply, no.


> The language was built because C++ was deemed too complex! Please see the thread about lazy [1] for a case where a question actually has an answer, but nobody seems to know it (and the person who does know it is hard pressed to explain the nuance that triggers this).

C++ doesn't have lazy. Lazy in D is a rarely used feature, so I'm not surprised there is less institutional knowledge about it, and it hasn't been thrashed as much as other features.


> * Critical bugs aren't being solved
> 
> People keep advertising D as supporting RAII. I'm sorry, but "supports RAII" means "destructors are always run when the object is destroyed". If the community (and in this case, this includes Walter) sees a bug where that doesn't happen as not really a bug, then there is a deep problem, at least, over-promising. Just say you don't support RAII and destructors are unreliable and live with the consequences.

If you're referring to #14246, I posted a PR for it. I don't see how that is pretending it isn't a problem. It is.


> * The community
> 
> Oh boy.
> 
> Someone who carries weight needs to step in when the forum is trying to squash down on criticism. For Mecca, I'm able to do that [2], but for D, this simply doesn't happen.

If someone is trying to squash criticism, I would like to see what you're referring to. If a post contains unprofessional behavior, like using f--k or harassing people, it will get removed. Simply being critical is not removed (if it was, this this thread would have disappeared).
August 23, 2018
On 23/08/18 14:02, Walter Bright wrote:
> On 8/23/2018 2:09 AM, Shachar Shemesh wrote:
>> functions may be @safe, nothrow, @nogc, pure. If it's a method it might also be const/inout/immutable, static. The number of libraries that support all combinations is exactly zero (e.g. - when passing a delegate in).
> 
> If, for example, a library functions allocates with the gc, then it can't work with @nogc code. But still, fair enough - if there are combinations which should work, but do not, please submit bug reports. If you have already, is there a list of them?

None of that continues to work once delegates are involved. I am yet to see a library that can accept a delegate and correctly create a function around it that matches its attributes.

And yes, I do include Mecca in this. I tried. It is too difficult to get right, so I gave up.

Attribute inference was supposed to solve this, but attribute inference is completely broken with separate compilation.

> 
> 
>> * Language complexity
>>
>> Raise your hand if you know how a class with both opApply and the get/next/end functions behaves when you pass it to foreach.
>  > How about a struct?
> 
> I presume you meant empty/front/popFront.
Indeed.

> 
> This is in the language spec:

How many people know that without resorting to the specs.
> 
>> Does it matter if it allows copying or not?
> 
> For the preference for opApply, no.

But it does for empty/front/popFront, which is exactly my point.

> 
>> * Critical bugs aren't being solved
>>
>> People keep advertising D as supporting RAII. I'm sorry, but "supports RAII" means "destructors are always run when the object is destroyed". If the community (and in this case, this includes Walter) sees a bug where that doesn't happen as not really a bug, then there is a deep problem, at least, over-promising. Just say you don't support RAII and destructors are unreliable and live with the consequences.
> 
> If you're referring to #14246, I posted a PR for it. I don't see how that is pretending it isn't a problem. It is.

When I first reported this, about 3 and a half years ago, the forum explained to me that this is working as expected.

#14246 was over 2 years old by the time you posted the PR. Once posted, however, it broke (I'm not sure why it broke, but did notice it deliberately would not work with @disable init structs. See my interoperability comment from above). Since then (over a year), no progress has been made except to revert the changelog that claims it was resolved.

When I talked to you about it at the last DConf, I got a reply that could be largely summarized as "yeah, we should probably do some flow analysis, sometimes".

The only time I got anyone to take this problem seriously was when someone on the forum would claim that D supports RAII, to which I tend to reply with "no, it doesn't".

So you will excuse me, but I don't think this bug is being taken as seriously as I think it should.

I get it, it is not a simple bug to solve. It is an unfortunate truth that some important bugs are not going to be easy. C++ went a different path with this (strictly setting when members are initialized). I get that this is a very unpopular feature of C++, and I can see why, but seeing how D struggles to resolve this issue, I can't say it is a mistake on C++'s behalf.

Shachar
August 23, 2018
On 8/23/2018 4:31 AM, Shachar Shemesh wrote:
> None of that continues to work once delegates are involved. I am yet to see a library that can accept a delegate and correctly create a function around it that matches its attributes.
> 
> And yes, I do include Mecca in this. I tried. It is too difficult to get right, so I gave up.
> 
> Attribute inference was supposed to solve this, but attribute inference is completely broken with separate compilation.

I'd like to see an example so I can understand exactly what you're having trouble with.


>> This is in the language spec:
> How many people know that without resorting to the specs.

This is a little unfair. It's plainly stated in the documentation for foreach. Heck, I wrote a C compiler and the library for it, and yesterday I had to look up again how strncmp worked. I refer to the documentation regularly. Back when I designed digital circuits, I had a well-worn TTL data book on my desk, too. If it wasn't documented, or documented confusingly, it would be a fair point.


>>> Does it matter if it allows copying or not?
>> For the preference for opApply, no.
> But it does for empty/front/popFront, which is exactly my point.

If front() returns by ref, then no copying happens. If front() returns by value, then a copy is made. This should not be surprising behavior.


>> If you're referring to #14246, I posted a PR for it. I don't see how that is pretending it isn't a problem. It is.
> When I first reported this, about 3 and a half years ago, the forum explained to me that this is working as expected.

The forum can be anyone saying anything. A more reliable answer would be the bugzilla entry being closed as "invalid", which did not happen.


> #14246 was over 2 years old by the time you posted the PR. Once posted, however, it broke (I'm not sure why it broke, but did notice it deliberately would not work with @disable init structs. See my interoperability comment from above). Since then (over a year), no progress has been made except to revert the changelog that claims it was resolved.

The problem was calling other destructors that had different attributes, such as the constructor being @safe but calling a destructor that was not. It's not an intractable problem, but I work on critical problems every day. It's just that everybody has a different issue that is critical to them.


> So you will excuse me, but I don't think this bug is being taken as seriously as I think it should.

It is a serious problem. (There are workarounds available, like using scope(failure).)

I'd appreciate a list of bugzilla issues you regard as critical to your operations.
August 23, 2018
On 8/23/18 8:03 AM, Walter Bright wrote:
> On 8/23/2018 4:31 AM, Shachar Shemesh wrote:

>>> This is in the language spec:
>> How many people know that without resorting to the specs.
> 
> This is a little unfair. It's plainly stated in the documentation for foreach. Heck, I wrote a C compiler and the library for it, and yesterday I had to look up again how strncmp worked. I refer to the documentation regularly. Back when I designed digital circuits, I had a well-worn TTL data book on my desk, too. If it wasn't documented, or documented confusingly, it would be a fair point.

On the point of opApply, the choice is quite obvious. Why would you put opApply in an aggregate if you didn't want to control foreach behavior? Once you think about it, there shouldn't really be any more discussion.

>>>> Does it matter if it allows copying or not?
>>> For the preference for opApply, no.
>> But it does for empty/front/popFront, which is exactly my point.
> 
> If front() returns by ref, then no copying happens. If front() returns by value, then a copy is made. This should not be surprising behavior.

I think he means, if the range ITSELF doesn't allow copying, it won't work with foreach (because foreach makes a copy), but it will work with opApply.

>>> If you're referring to #14246, I posted a PR for it. I don't see how that is pretending it isn't a problem. It is.
>> When I first reported this, about 3 and a half years ago, the forum explained to me that this is working as expected.
> 
> The forum can be anyone saying anything. A more reliable answer would be the bugzilla entry being closed as "invalid", which did not happen.

There have been several people who I have spoken with in person, and also seen posted here, that say the forum is unfriendly or not open to criticism of D. I feel it's the opposite (in fact, most of the die-hard supporters are very critical of D), but everyone has their own experiences.

There are many people who post short curt answers, maybe even cynical. But this isn't necessarily the authoritative answer. Where I see this happening, I usually try to respond with a more correct answer (even though my voice isn't authoratative exactly), but the sad truth is that we can't spend all our day making sure we have a super-pleasant forum where every answer is valid and nobody is rude.

In reply to Shachar's general point:
This whole thread seems very gloomy and final, but I feel like the tone does not match in my mind how D is progressing. "Every single one of the people [at Weka] rushing to defend D at the time has since come around." Seems like you all have decided to either ditch D internally, maybe moving forward, or accepted that Weka will fail eventually due to the choice of D? It sure reads that way.

This is in SHARP contrast to the presentation that Liran gave at Dconf this year, touting D as a major reason Weka was able to develop what they did, and to some degree, your showcase of how Mecca works.

My experience with D is that it has gotten much better over the years. I suppose that having worked with the earlier versions, and seeing what has happened gives me a different perspective. I guess I just don't have that feeling that there are some unfixable problems that will "kill" the language. Everything in a programming language is fixable, it just matters how much pain you are willing to deal with to fix it. If we get to a point where there really is a sticking point, D3 can be born.

I do feel that we need, in general, more developers working on the compiler itself. So many of the problems need compiler changes, and the learning curve to me just seems so high to get into it.

-Steve
August 24, 2018
On 24/08/2018 12:55 AM, Steven Schveighoffer wrote:
> 
> I do feel that we need, in general, more developers working on the compiler itself. So many of the problems need compiler changes, and the learning curve to me just seems so high to get into it.

It depends, some parts are very easy to get into.
But development in general definitely isn't welcoming to get into.

In general the bar is very high and it isn't possible for a regular to jump in and take ownership of a part of it that doesn't have anybody interested in it and that's a real problem.
August 23, 2018
On 23/08/18 15:55, Steven Schveighoffer wrote:
> This whole thread seems very gloomy and final, but I feel like the tone does not match in my mind how D is progressing. "Every single one of the people [at Weka] rushing to defend D at the time has since come around." Seems like you all have decided to either ditch D internally, maybe moving forward, or accepted that Weka will fail eventually due to the choice of D? It sure reads that way.

I'll clarify, in order to not create the wrong impression.

No, Weka is neither ditching D, nor is it banking on failing. We're doing pretty good as a company, and D will not change that.

What I did mean by that is that the enthusiasm from D has *greatly* diminished. Many (but not all) developer will definitely not choose D for our next project, should the choice be ours to make.

Like I said in my original post, it is not even in consensus whether picking D to begin with had been a mistake. Some think it was, some think, even in hind sight and after being more or less disillusioned, that it was still better than picking another language. As such, it is not even universally true that engineers at Weka regret going with D.

I think Mecca is a great library, and I'm very proud of writing it. There are certainly aspects of it that would not be possible (or, at least, highly impractical) in any other language I know.

With that said, it is also true that there are aspects of Mecca where D was holding me back from doing stuff I knew I could do much easier in C++. There were also areas where run-time bugs were discovered during integration with the main Weka code base (integration that is still ongoing) that were difficult to diagnose at best (and yes, I have it on my todo list to submit a PR to fix some aspects of some of them).

Example of something I couldn't/wouldn't do in any other language: the second form of spawnFiber:
https://weka-io.github.io/mecca/docs/mecca/reactor/Reactor.spawnFiber.html

The fact that the arguments for spawnFiber are the arguments for F, and that's verified by the compiler, no casts, no inference, no code bloat, is huge. I am sorely going to miss it at my next project (which, like I said, will not be written in D).

On the other hand, look at ConnectedSocket.connect:
https://weka-io.github.io/mecca/docs/mecca/reactor/io/fd/ConnectedSocket.connect.html

Why do I need two forms? What good is that? Why is the second form a template? Answer: Because in D, structs can't inherit, and I cannot define an implicit cast. What I'd really want to do is to have SockAddrIPv4 be implicitly castable to SockAddr, so that I can pass a SockAddrIPv4 to any function that expects SockAddr.

Except what I'd _really_ like to do is for them to be the same thing. I'd like inheritance. Except I can't do that for structs, and if I defined SockAddr as a class, I'd mandate allocating it on the GC, violating the whole point behind writing Mecca to begin with.

----

To summarize: Weka isn't ditching D, and people aren't even particularly angry about it. It has problems, and we've learned to live with them, and that's that. The general consensus, however, is that these problems will not be resolved (we used to file bugs in Bugzilla. We stopped doing that because we saw nothing happens with them), and as far as the future of the language goes, that's bad news.

Shachar
August 24, 2018
On 24/08/2018 1:22 AM, Shachar Shemesh wrote:
> Except what I'd _really_ like to do is for them to be the same thing. I'd like inheritance. Except I can't do that for structs, and if I defined SockAddr as a class, I'd mandate allocating it on the GC, violating the whole point behind writing Mecca to begin with.

Between multiple alias this, DIP1000 and potentially signatures, that should be possible. Although you won't need to use override at least ;)
August 23, 2018
On Thursday, 23 August 2018 at 12:03:59 UTC, Walter Bright wrote:
> I'd appreciate a list of bugzilla issues you regard as critical to your operations.

Sorry to weasle in, but https://issues.dlang.org/show_bug.cgi?id=2043
Sorry for childish behaviour in bugzilla (my last comment), but this bug makes me radiate in gamma-rays, because the current D behaviour is stupid and invalid, the workarounds (hacks) are incredibly ugly, and, on top of that, the bug is 10 years old. There are also tons of other bugs, inconsistencies etc. that I stumble upon regularly, they all were in bugzilla long before my "discoveries".

Ok, let me be brutally honest. These types of things really piss me off in D. IMHO top-tier devs are not focused on really important things. For me, a long-term D user, proper closures are much more relevant than D/C++ Kama Sutra. I don't have any C++ code and I don't intend to write any. I want to and do write D code and I want it to work *at least* correctly. But Walter, our compiler-fu black belt master (not making fun of him, I really respect his expertise), is more concerned about "poor" C++ users (which have all the luxuries) than about peasants like me with their puny #2043's, which he could solve by a single roundhouse kick (and maybe a restomp of the groin).

But I get it, it's a community-driven project, so "if you want it, DIY or get lost". I choose the latter, because my compiler-fu is rather weak, if exists at all. I still love D, but more like a good book, than a reliable tool. It's funny and sad at the same time, that I regularly find nightly Rust more reliable than stable D. So the obvious move for me is to stop arguing with the Party and simply choose other party that better represents and addresses my needs.

Don't get me wrong, I'm not ditching or D or saying it's crap, I'm still using it from time to time, but I will likely not choose it for any "serious" project (even hobby). Just tired of stomping on all the occasional caltrops, which are well-known, marked on the maps, but not being removed because children starve in Africa.