This is the feedback I collected from the Gripes and Wishes campaign that ran from December-March. Thanks to everyone who participated.
I've mostly just dumped the raw feebdack into loosely categorized lists. Whether the categorizations are all accurate right now is irrelevant. As we work through everything here and decide how to proceed, we'll put things where they belong.
A few notes:
- I've excluded Bugzilla issues that have since been closed
- I've tried to include examples and suggestions that were provided along with the points, but I have cut out some bits that were irrelevant or extraneous.
- I've not included compliments. I wanted to focus only on things we need to fix/change. But the compliments were received and much appreciated.
- There were three pieces that I decided not to breakdown into actionable items and included in longform instead. Those are at the bottom of the document.
- I'll probably update this list after our planning meeting tomorrow.
So, the next steps related to this. Generally, we need to:
- establish some high-level goals (and this has been done)
- go through this list to see what fits with those goals, what doesn't fit now but could be done later, and what is unlikely to ever fit any goals
- discuss additional ideas from our own wish lists (and I'll update the document with those once I have them all)
- prioritize everything we've decided fits our current goals
- publish categorized task lists
- work out who among us is responsible for what
- get things done
That last one is the hard part. I'll have more to say about it when the time comes.
- Process
- Language/Runtime
- Phobos
- Compilers
- Tools/Ecosystem
- Documentation/Website
- Community
- Longform Feedback
- Need a roadmap or vision
- Proper direction, vision documents. Don't try to please all users, you'll never do that. Forge your own identity and pursue it. Look at our competition such as Zig, Rust or Nim. They don't work hard to bring C or C++ users or any other languages users. They just make decisions and stick to them. Some people won't like it, but many users of other languages like it and move to those languages, adopting their customs rather than trying to bend them to what they knew. There's a tip in the dating world - "don't chase women, instead become a man that women want to chase". I don't want D to go for users of other languages. I want D to be the language users of other languages go for.
- Phobos leadership, yes this is meant to be Atila, but fact is with the Unicode table generator PR, Atila in the past had made statements on another PR but didn't green lit it in new one. It sat. A critical PR sat with no leadership comments, which we have since learned was important to Symmetry…
- I still feel that the goal in D is very unclear. For example, C and C++ didn't need to get a clear goal. We have had the BetterC/Full D division right now, which only made things worse. I personally despise betterC as I want the entire language, and in my understanding, betterC is the hawkish way to run D on any platform without having to implement. Having done a runtime, I believe that our runtime could be thoroughly improved to be supported in more platforms. But that would be questioning the goals. As far as I understand, Rust main reason to exist was creating a language which compiled to web assembly while bringing safe features. While Go is a native language which specializes itself in dealing to network related features. D tries to bring both low and high level features to your hand and make you use the best way possible. This is a generalist approach and I can understand about that, the problem is that D doesn't excel at anything. That happens because I have a view that D doesn't have a good foundation right now (just look at why SDC was created). And now we're lost thinking about if we should make the std lib betterC while there's plenty of people saying we need a better GC.
- Freeze d2, start d3. Name it something spiffy and new to distance itself from D's legacy. Let the community decide D's future not Walter. That's my concrete suggestions..
- Why haven’t we implemented a console library to make Unicode work on Windows? Lack of leadership long term. Every single person runs into this.
- I don't want any new features. I don't want changes. It's exactly the opposite that I want. I want stability and predictability.
- The way Walter completely bypassed the DIP process to pull in a huge change such as ImportC is an appalling practice. So I would wish that the DIP process was inclusive to everyone.
- Rip apart the dip process down to just the community review and a well-written template.
- Attempting to reach a point where something useful could happen with multiple alias this was shown to be obviously stymied. I lost confidence that the huge effort of writing a DIP (because of the manifold constraints to be satisfied that such entails) would have a worthwhile likelihood of achieving any change whatsoever. My situation was like other situations I found in the forums. My view was and is that in all likelihood at some late stage in the process Walter would nix it. This is the point where I permanently lost interest in involvement in the future of D. It wasn't the first place I was discouraged, but this is the point at which I depressingly crossed a line. I have had other possible proposals in mind. But I'm not even going to start discussing them. I'm just going to use D when it's the right tool for the job. And I am not going to try to contribute anything to its future.
- I wish that D focused more on improving third party support, such as freezing the features already in the language, to fine tune and fix them, with a huge effort of bringing major 3rd part dependencies like vibe-d, emsi-containers, libasync, and others up to part and promoting them. Most 3rd party could be focused to be included with the std, or at least distributed with the language as an official way of doing things. I want to see a feature freeze, and moving all experimental stuff to D3.
- It's really difficult to build up any form of motivation to work on D. Whether it's a DIP which we've all seen are generally large time sinks and require decent effort, however provide minimal payoff. I haven't made one myself since I know it's a completely futile effort. Or whether it's working on the ecosystem where, considering D's extreme lack of "footfall", makes the time-benefit ratio of most things completely lackluster. It's just difficult to want to contribute and to try and make some of my more grand ideas come to life, simply because I have good reason to assume it'll just be left in the dust. And then of course there's almost 0 job prospects for D with no real sign of anything changing anytime soon which yet again begs the question - why should I bother? So I guess my wish would basically be: "I wish D was popular enough to warrant the effort". I understand the chicken-and-the-egg situation here, but it doesn't negate the impact my wish has.
- Keeping contributors coming and happy is probably the biggest improvement I could see core D making.
- Too much focus on advanced over the basics. We have some advanced language/library features, and yet we can't even do a static initialized associative array. D doesn't have a proper container library, and any attempt is shut down because no one can decide on memory management strategy (GC only? @nogc? What about betterC? how about allocators?). Some language deficiencies are covered by library solutions, but those come with caveats too. There's nothing like language features that IDEs can recognize and reason about. A library solution might be nice, but when you make an error it still dumps several screens of template error soup.
- To many unfinished features. The preview switch for shared isn't turn out by default. The implementation of properties isn't finished. Compile-time function engine can not replace this as it doesn't support binary operators or unary operators when it comes to using two functions. Feels like Walter is keeping getting sidetracked to personal projects for dmd rather than fixing what needs to be done.
- Break compatibility often. For me code breakages is not an issue in general. I think that D is leaning towards stagnation under the guise of language stability. I think a reasonable breakage policy (announced well ahead, deprecation model, testing top N dub packages and top Github D projects for usage of language/phobos features) can allow the language to flourish without breaking too much code.
- I’m sympathetic with Walter’s dilemma of wanting to add new features and then getting lambasted for not finishing other ones. When he focuses on bug fixes then he gets criticism about stagnation. I don’t know the answer here, but the current approach doesn’t seem optimal.
- Stop pretending D is a corporate language. There's a formal meeting, there's a yearly school community building program, and there's a formal process with many rounds of review for any and all compiler changes; none of which seems inclined to address anything I care about. Stop. You have a community of meta-programming-crazed iconoclasts, who can and will make their entire toolkits like Adr, or the 5 or so people who went off to make their own language. You are simply not Go where you can have strict idiomatic language and the std is funded with google money. Or C++ where Microsoft with Enterprize-Grade mediocrity implements whatever API you put out. Either you believe this small community has great 1000x programmers or you don't and we are doomed anyway from lack of manpower and money. You should be giving the 1000x programmers their sandboxes to let them shine, and push them close enough together they can see each other, but walls to denote which sandbox is whose.
- Refocus the people willing to play
with otherswith the official style guide to fixing compiler bugs, and delete old unmaintained parts of the std. - Don't herd cats, just clean out the litter boxes.
immutable struct
s. Please use them internally! It's just very, very obviously a feature that just isn't dogfooded by the core devs at all.- You know what bugs me most? The feeling of being ignored and dismissed. I know the reply is usually "we didn't ignore you we just disagree" but.... there's plenty of evidence that it is just outright ignored. From Andrei flat-out saying "I stopped reading after the first sentence" (then saying some crap I specifically addressed in the following paragraph) to Walter's stubborn repetition of debunked nonsense over and over, without even pretending to acknowledge the alternatives. If you're not going to pay people money, you could at least pay attention. But instead, when the leadership does look at you, it is to nitpick, belittle, dismiss, and censor. No wonder retention is so abysmal. I do hope something happens. You know, I actually like Walter and Andrei when we're working together on equal footing. The Beerconfs are generally pleasant, etc. But when they start exerting authority, Walter is frustrating and Andrei was grating.
- D lacks adoption, probably because of some of the previous points here, and also the terrible publicity it got from the Tango/Phobos debacle, and other potential issues. I think this is quite of a vicious cycle: companies don't invest in D because there is limited traction to the language, which makes it less likely to get traction. Sure, this changes, and D gets more users over time, like how Python took years to get a big traction as well, but this is really impacting D. It saddens me to see other (probably great and interesting programming languages) get traction in a much faster way (ok, Go and Rust are cheating as they were backed by corporations, and Go is somewhat less hyped now and maybe? declining). But D could do much better in that area.
- Maybe I'm a bit biased, but I find that there isn't really an emphasis on clean code in the D community; a lot of projects I look at have massive files of several thousand lines of sparsely-documented code, and I think this might stem from a few things: Unit tests add a ton of clutter to the source; Version statements and alternative code for different versions tends to lead to huge files. I think that conditionally importing separate modules based on the version is a cleaner solution in some cases, such as Phobos packages for
std.socket
orstd.path
; I'd believe that many D developers look to Phobos as a "gold standard" of what D code should look like, since it's likely the first library they'll be using. But Phobos's modules are all huge and full of the aforementioned verbosity, and I think that D could improve by making Phobos more readable. - I feel there is little need to try to compete with Rust, however DIP1000 at least allows memory safety to be part of the argument to use D. Really it serves full stack engineering with a focus and productivity. From our use, it is incredibly well suited to tooling, a place that Go typically occupies.
- We do have a shortage of bug fixing power. There are still plenty of known compiler crashing bugs regarding the bottom type for example. An even worse example was Issue #22495. A publicly known security vulnerability, that should be among the most urgent if not THE most urgent thing to fix, took a year to fix. I don't have a precise idea where that shortage comes from, though. Some of it is undoubtedly just the lack of manpower, some can be attributed to other issues.
- Walter is bad at acknowledging his blind spots when people point them out. He is always diligent and kind, and smart in general. But it often happens that he continuously misses the same point in debates despite it being repeatedly made by different people, or if he gets them he addresses them badly. The acceptance and then dismissal of DIP1028 is a good example. There was an overwhelming support for the idea to keep
extern (C)
code@system
by-default, but the DIP was accepted without changes or reasoning. After this caused an uproar, Walter explained. Most still disagreed, but his reasoning was well-founded enough to deserve further consideration, unlike his earlier half-hearted answers to the same concerns at the final review. Had he brought his best counterarguments up when the DIP was still at reviews the discussion could have moved forward. Failing that, adding them to the acceptance rationale would already have been a clear improvement. - The feedback cycles at the code repositories. The reviewers don't always do their best to minimize the number of review cycles required. If someone with approval authority reviews and has some nitpicks, he should nonetheless approve the PR otherwise so there's no need to wait for his another look when the nits are fixed. But I must say this is much less of a problem than it used to be, since our pull request managers are doing such excellent job.
- Development for dmd on windows is bad. The runtime has been merged with dmd already, why hasn't the visual studio project updated for it already? It is easier to create a visual studio project for it then to write a program that generates visual studio projects.
- Breaking changes. So, to be fair, usually I'm not affected by most of the releases. But when it does, it does strikes very hard. I feel like the main problem is that its missing some documents over migration. I felt that on dub which I'm currently version locked because it is not able to generate shared library correctly. While on D language updates, I feel like we're still missing better debugging tools to track where and what happened.
- I feel that although I really like how importC is attractive for people willing to migrate their codebase to D, I feel like it was over advertised before being really useful.
- Some parts of the language are poorly defined when it comes to metaprogramming, e.g., inspecting modules via built-in traits often produces surprising results that can differ significantly between compiler releases. It would be nice to have these well-defined and tested.
- Pay-as-you-go runtime. The templatization of DRuntime ought to help with inlining and give us even greater efficiency.
- It's pretty difficult to write portable-ish inline assembly for non-x86 platforms. Inline assembly has been really useful for my bare metal shenanigans, and would be a lot easier for me to use than the equivalents GCC and LLVM have for ARM and RISC-V.
- Need static initialization of AAs
- Add my name to the list for static initialization of AAs. I just ran into yet another situation where it would be nice to have the better initialization syntax for associative arrays. Mostly to allow for terse code, the initialization itself could happen at runtime, AFAIK that wouldn't bother me any.
- A minimal, bare-metal runtime that doesn’t require BetterC
- Either remove
__traits(compiles)
andis(expr)
or make them redundant and discouraged. At best, they represent shortcomings of D’s metaprogramming. At worst, they cause silent bugs. __traits(compiles)
is an abomination. It turns a nice, documented compile error into a cryptic template error that leaves no evidence of the actual problem. What's more, on a type system level,__traits(compiles)
is literally "ON ERROR RESUME NEXT" (if you don't know Visual BASIC, it's "skip commands that fail for any reason, resume on the next line". Sound familiar?). At best it turns good errors into bad errors, at worst it turns errors into wrong runtime behavior. And you have to use it! - because there's no way to inspect errors more finely or to propagate template compile errors to the caller without halting compilation. We need a compile-time equivalent oftry
/catch
, inspection of compile errors, and a way to synthesize a new error that builds on captured errors in the language.@safe
by default for functions with bodies. Memory safety rules! But I don't want to automatically trust code that hasn't been checked. Especially foreign C code that frequently has awful CVEs attached to it, like c runtimes. Manually marking them@trusted
or making a@trusted
wrapper is a much smaller hassle than trying to track down memory corruption. At least@trusted
is greppable.@safe
by default. I am not too sold on the idea of safety as a language feature personally, but I think the current state of optional safety is even worse. Most projects don't bother with marking the code as @safe because it's too much effort, and @safe projects can't use such projects for this reason. @safe is consuming a lot of manpower effort, so I think it should be either dropped or enforced. With enforcement, it'd be a painful period, but sooner or later most projects would transition to it. With current optional behavior, most projects don't bother and safety relies on network effect to be used widely.- change to
@safe
by default const pure nothrow @safe @nogc
: Please find good defaults! Consider impure, gc, mutable, ... or at least!static
,!pure
,!nogc
. Maybe defaults should be settable per module. Most of my code is yes-gc, but in a few select modules, I try to write everything as@nogc
. Per-module defaults sound nice.- accept
@trusted
expressions (to get rid of the ugly lambda workaround) and deprecate the use of @trusted on functions. - Signatures. Template constraints require too much boilerplate, the diagnostics are terrible (though there have been improvements, they are still quite difficult to read), and because of #5, can slow down compilation, which regrettably leads me to omit them fairly often in my own code. Signatures can give us the same guarantees with less boilerplate.
- Named parameters! Please implement DIP1030.
- named parameters with support for perfect forwarding and compile-time introspection
- wen named parameters? :)
- built-in duck-typed record types playing nice with named parameters
- Please don't let OS segfaults be the only way to handle null dereferencing. I want a nice stack trace! Having to fire up the debugger and reproduce these is annoying enough, but when a nice debugger doesn't even exist for the bare metal platform you're working with, it's enough to ruin my day!
- Remove ImportC (or move it to D3).
- Stable D branch that would only contain bug fixes with very rare occasional features added/removed
- WASM projects can't use Mir (betterC) which cannot use my stuff (disabled runtime) and I cannot use regular D-with-runtime. Ecosystem get a bit more fragmented than necessary, which is made worse by the DIY programmers D tends to attract. Should be easier to share code…
- With D you have things like
@nogc
,@safe
,-betterC
which fragment the community. There's also@live
, which apparently also had some work done for it, but it's hard to tell what benefits it will bring and whether it's actually worth it in the long run. Similarly, a lot of work is done on ImportC andextern(C++)
, there's even been language features added to D to promote better interaction with C++. I don't see it beneficial to the language as a whole. The main advantage of D is that it isn't C/C++. We may want to interact with C/C++ libraries, but we shouldn't bend our language too much to facilitate that. Unless we want to be a glue language for C++ code, which some in the community are happy with, but it's not a very noble goal in my opinion. - Too many language features. While more language features may not hurt, they add additional maintenance overhead. Maybe I am in the minority, but I feel like there are many features in D that don't really get used and could be dropped. For example contracts I haven't really used much in D projects and I don't feel like they add much over standard asserts.
- Limited WASM support. Recently I've been participating in some game jams, and the best way to make a game for a game jam is to make a web game, because people are wary of running untrusted native executables. Also, these games often are simple and require basic 2D graphics to get going. I'd really love to make my games in D instead of other languages, however it doesn't seem like D is there yet. While there are some interesting projects like Spasm and the WASM compilation in LDC, it's not streamlined and there is very little documentation on how to approach it. There are only few sample projects, and most require a lot of effort. I feel like what D needs is equivalent to these projects in Rust’s wasm-bindgen and js_sys. Even languages such as Go are a much better option for WASM development at the moment, and that's a fully GC language, so GC is not an excuse.
- No progress feedback with built-in
unittest
blocks. That makes it harder to figure where a crash happens when one of the tests actually results in a complete crash instead of an assert failure. It would be nice to have (optional?) progress information onstdout
like the module name and line number of theunittest
block that is about to be run. - tuple unpacking
- consistent forward reference handling; metaprogramming and introspection that actually works
- floating-point determinism at the language level (allowed to vary by target, but should be clearly documented; runtime and CTFE results should always be consistent, can have additional types with relaxed semantics)
sumtype
(with static checking), pattern matching- Sumtypes are great, but they should be built into the language with a rich suite of verbs to operate on them. Also, the lack of implicit conversion is painful. Why do I have to write
FooSum(Foo(1, 2, 3))
? The compiler knows perfectly well what the parameter type is. I know Walter doesn't like implicit conversion on call, but we don't have this sort of issue for integers. Why canint
be implicitly converted tolong
? Becauselong
is a type with a domain that contains the entire domain ofint
, so there cannot be data loss.SumType!(A, ...)
is a type that contains the entire domain ofA
, and yet I cannot implicitly convertA
toSumType!(A, ...)
. This is a problem that arises entirely because Walter doesn't trust his programmers to be responsible with implicit conversion constructors. Well, fine, but then don't force a basic type likeSumType
to depend on a user-visible feature. Either make it built-in (and give us implicit construction), or give us implicit construction for any type. - Alternative to OOP is possible, but is showing it's age. We are left with what C can do (
struct
,enum
,union
). To enhance the features we have template (sumtype, tuples), but they make the D experience worse: incomprehensible template compilation errors; slower compilation speed. That's even more sad when you learn that both Java/Python/C# caught up with Tagged Unions and Pattern Matching.. including C++.. and that's without mentioning the newer languages (rust, zig). So when you step outside of OOP, you have to write ugly code everywhere. Having Tagged Union built in helped rust and zig not need OOP at all, it should be available in D too. - Integration of
std.sumtype
as a language feature, in conjunction with bottom type + ternary expressions, could be a much nicer way to handle application exceptions, rather than full unwind, etc. - null safety
- local instantiation for member templates
- correct allocation of closures (particularly in loops)
- standard built-in and concise tuple syntax
- linear/affine typing/ownership type system that interacts well with GC
- type system soundness in
@safe
- polymorphism/type erasure, in particular for attributes (but I would like it in general)
- multiple alias this using standard import lookup rules (I don't care much for the implicit conversions, just the lookup semantics)
- Alias this is still restricted to one instance always, after all these years.
opStaticIndex
/opStaticSlice
- type classes / some standard way to add UFCS methods to a type from another module that are then visible in an instantiated template from a third module
- mixin identifiers
__local
,static break
andcontinue
(see DIP 1010)- template literals
- AST introspection
- consistent treatment of operators for built-in types, e.g.,
1.opBinary!"+"(2)
should work. - operator overloading should combine orthogonally with UFCS
- better support for subtyping (expose the concept to user-defined types, e.g.,
Range!(const(T))
could be a subtype ofconst(Range!T))
and any other features required to support a good container library async
/await
(or similar)yield
(or similar)- range literals
- more lightweight coroutines
ProtoObject
- I'm eagerly awaiting a D3 where we inherit from
ProtoObject
by default. I wouldn't like to writeclass X : ProtoObject
. - special treatment of qualified types, in particular qualified reference types (e.g.
immutable
classes should allow conversion of references fromimmutable
to mutable) - non-deterministic semantics, with as little undefined behavior as possible, in particular for type/function qualifiers
- compile-time fixed-point support (e.g., with
struct S(T){ T* next; }
,fix!S
gives a singly linked list) - flow-sensitive typing
- strong variable updates
- non-lexical variable lifetimes
- parametric polymorphism, in particular for type qualifiers
- some amount of dependent types
- I would like to see some kind of solution to issue 1807. It was frustrating to read comments on the DIP (1023) that question its value when it is so obvious to me. Perhaps there is a difficulty in communicating it’s value. The problem is that one or two people expressing a negative view basically vetos any further work from being done on it. What is the point of bringing the work to a good enough place to be under consideration if it is known they will reject it anyway?
- I wish
@property
would be completed - by makingopOpAssign
work (a combinedget
/set
) and forbidding to take the address (if taking the address is desired, either use a function or a value type). Please! Simply let us try it. Everybody who doesn't like the described solution can simply avoid using@property
at all. - I wish Issue 259 could finally be fixed. We have a working solution, but it would break existing (wrong) code, that relies upon the misbehavior.
- I wish we could generally ignore downward compatibility to C in cases where C is simply bogus. Especially the integer promotion rules should be reworked:
(byte or short) + ushort ==> int
, so why not(byte, short or int) + uint ==> long
(instead ofint
)? Slower on 32bit machines, but today 64bit machines are the majority. Use explicit cast of theuint
toint
to avoid that. This is the only change that's incompatible with C, but for the better! We can have a long deprecation period on this one, maybe even forever.signed + ulong ==> mismatch error
(instead oflong
). Use explicit cast to avoid that. This is different then in C, but compliant with the rule "Either behave the same or doesn't compile".byte + ubyte ==> short
(instead ofint
). This is not so important because int is more efficient on 32bit machines and this promotion cannot produce problems, but it would be more and this promotion cannot produce problems, but it would be more consistent. On 16bit machines it would even be faster. - The language sometimes feels a little cluttered, partly because of the MANY paradigms that the language supports, there are so many keywords to remember that do different things in different contexts. While this makes D an extremely powerful tool it can be a little challenging for programmers, I can’t imagine how a total newcomer, that doesn’t know C++ or any other newer C-like languages, must feel when trying to learn D. The overall learning curve of D is mostly fine though, especially since many aspects of the language are more intuitive than the analogous features in C++ or the likes.
- D has become a really complex programming language with almost every possible features anyone can dream of. This makes it quite difficult to bring at my company as my colleagues don't have a solid background in programming. We are currently using Python, C# and Javascript. From those 3, only C# comes close to D, and it is already difficult for my colleagues to grasp the relative complexity of C#. This is where I am limited to bring D.
- Make an n-element array index from element 1 up to and including element n, rather than the C-style 0 to n-1. This would reduce off-by-one logic errors as, IMO, most people start counting from 1 not 0.
- Create a new first class (not in a library) value type 'variable length array’
- The lack of
this()
for structs is just stupid. Do you know what sort of code we write?struct Foo { this(int) {} } Foo foo() => Foo(0);
This accomplishes nothing and helps no-one. And no we can't useopCall
becauseimmutable
. - Alias lambda arguments are a very cute approach, and I adore them, but they're stupid. Lambdas should be values, not symbols. This is directly responsible for D's ongoing inability to declare class methods with alias lambda parameters, and it's an unprompted own-goal. Lambdas as a value that represents a context pointer solve the same problem, just more cleanly. This is one instance where I think Walter saw that he could do something and didn't think about whether he should do it, or if there was a better way. But we're stuck with them now.
- Our team had other matters to prioritize, but we finally found time today to discuss the subject in depth at our meeting. We have come to the conclusion that we are very satisfied with the D language. We notice how D greatly improves our efficiency. We have one minor annoyance with the syntax, but other than that we don't really have gripes with the language. However we do have some concerns which we would like to share. Before I write about what we find annoying with the syntax, I must stress that, ultimately, we find it inconsequential and that it isn't really an issue for us. We really don't care if you do anything or not. But you asked for this, thus we deliver what you asked for. Most people on this earth learn C, C++, C# or Java as their first programming language where the cast operator is a simple type enclosed within parentheses. D doesn't allow those. It's not that D doesn't understand the C-style cast; a D compiler will output a message something to the effect of telling the programmer not to cast like that. To us, it seems like the compiler should just accept it. We have read on the subject and we know it supposedly makes the code clearer. If anything, it just makes casting something that is annoying to write the few times one has to do it. D usually makes things more compact, concise and much less verbose. That's what makes code clearer. If typing out full words and sentence-like code was making code clearer, COBOL as well as languages like Visual Basic and Pascal would be the mainstream instead of being moribund as they are now.
- D interfaces very well with C libraries, but it still requires to create bindings which also implies to understand C (to be able to read/understand the library's functionalities). Sadly, working in a small company makes it quite this task impossible to do as it would always require some time to create those bindings instead of using an ecosystem where everything already exists. (Note on this: I don't really like to be importing/depending on libraries that are too big to understand or that impacts how the code will be designed, so I still try to do things "vanilla").
- Consider keyword inference. The compiler already infers keyword for function template instantiations, this might be nice to extend to normal methods. Should inference become the default? Should there be three modes per keyword (e.g.,
pure
):pure
,impure
, and aninferpure
? - I don't mind prefixing UDAs with
@
. But language keywords with@
are ugly (@nogc
,@live
,@safe
). Classic OOP code looks nice withabstract
,final
,override
, ..., that all don't need@
. - Non-nullable class references would be nice. Sure, I can have my personal convention (no member is null after the constructor, no function argument may ever be null) or write a library type. But even a library type has drawbacks: It's nonstandard, it can't enjoy covariant return types, it doesn't behave like a mathematical functor unlike
const
. - According to Walter in the January 2023 Quartely Meeting, sum types won't be the focus in D anytime soon, in favor of robustness. That's 100 % reasonable. But if sum types appear, non-nullable class references can go hand-in-hand with them: The nullable reference ("X" in D2, in other languages "X?") is really a sum type of the non-nullable reference ("X") and typeof(null). And "?" can become universal shorthand for "sum type with typeof(null)" not only for non-nullable class references, but for any type.
- Walter likes NAN values, I don't. :-) I'd rather have separate types to allow/disallow NANs or errors, ideally with a functorial relation between them. 100% reasonable. But if sum types appear, non-nullable class references can go hand-in-hand with them: The nullable reference ("X” in D2, in other languages "X?") is really a sum type of the non-nullable reference ("X") and typeof(null). And "?" can become universal shorthand for "sum type with typeof(null)" not only for non-nullable class references, but for any type. (See this forum post). Timon Gehr considers null a problem and appears well-versed in type-system design. When the idea of sum types or non-null comes up again, ask him for input. :-)
in
contract not checked in interfaces (Issue #12247).- Unimplemented interface method from abstract base class not detected (Issue #21321)
- I don't like unchecked exceptions. But I haven't used Java's checked exceptions or C++23's std::expected yet, maybe I'd like those. For more alternative error-handling ideas, maybe consider how the Zig programming language defines and returns errors. It's a hard design question, I have no good suggestion. I try to write code that avoids raising errors altogether.
- Personally, I think that D should require each function to declare exceptions that it throws, similar to Java's checked exceptions. Thankfully the use of exceptions is not quite so prolific as Java, but it's annoying that exceptions can potentially be thrown from anywhere, at any time, without warning (barring
@nothrow
functions, of course). Adding an explicit "throws exceptions" declaration to a function would greatly improve my day-to-day in dealing with any third-party library I want to use without having to inspect its code. - UFCS should work for local functions, too, not only for globals.
- Should UFCS also allow to call class methods like C functions?
method(object, arg1, arg2)
. There are proposals for C++ for this. - Trailing commas in D are excellent! In C++, I'm annoyed every time when I can't write:
void foo(int a1, int a2, ),
which is annoying in C++ when I write one parameter per line. - For an array, the
.length
property should beint
, notsize_t
. Likewise, in aforeach
loop with a separate counting variable, e.g.,foreach (i, element; collection)
, I would like i to be declaredint
, notsize_t
. - In array-indexing brackets, e.g.,
arr[0 .. $]
, the$
is shorthand forarr.length
. I'd like the$
as an abbreviation for length elsewhere, too, i.e., I'd like to writearr.$
forarr.length
. - In array-indexing brackets,
[a .. b]
means exclusive right-side bounds, but in a switch,case a .. b
means inclusive right-side bounds. That's inconsistent. I don't usecase a .. b
much, but when I do, I'm always overly careful. Exclusive is good. .sizeof
,.alignof
,.offsetof
,.stringof
are all postfixed, buttypeof()
must be prefixed. It would be nice to also allow postfixing.typeof
in the spirit of UFCS. It's not a big concern, but it costs a moment of thinking.- Delegates have a number of weaknesses. First off, there is no way to allocate, deallocate or duplicate a function context yourself for them. You can only have a controllable delegate context by referencing a member function of a struct. Works, but clunky.
- the
const
,inout
andimmutable
qualifiers are not really transitive with delegates, since even an immutable delegate can have a pointer to mutable context. - I wish we had a standard type to represent dynamically typed tree-like data. Think content of JSON or SDL file, but in a binary form. D is certainly capable of representing such data in a data type, but it's such a common need that I think there should be a standard type for that, instead of everybody cooking their own poison. It should also be easy to write literals of that type to the source code with a nice syntax. The syntax needn't quite match JavaScript, Lisp or Lua, as those languages are specialized to that sort of stuff, but it shouldn't be far off. Granted, the standard library has some solutions - namely,
std.json.JSONValue
andstd.variant.variant
, but both of those are intended for slightly different purposes and are of somewhat outdated design. - D introspection capabilities, while generally great, have all sorts of shortcomings when it comes to function parameter lists. You can certainly tell the number and type of parameters of a function or a delegate, but you have no principled way of knowing which arguments are
in
,out
,ref
,scope
,return scope
orlazy
. You lose this information as soon as you fetch the argument type tuple out of the function/delegate type. There is no way AFAIK to manipulate a function type without losing this information. You want to reverse the argument list while keeping the storage classes? Tough luck. Also you cannot introspect, let alone manipulate, names of the parameters. Nor default arguments. - It would be nice if we could bring back
typedef
as a way to define a shorter or clearer symbol name for any other symbol. E.g.,typedef ReturnTypeOf!(SomeFunc) MyType
. The idea being that for very complicated types we could have simpler names in error messages and possibly in the binary as well. - Improve IFTI with C++ style user defined deduction guides. (See this web page and this forum discussion).
- D lacks the ability to deduce template alias parameters (see this forum post and this forum post). DIP 1023 is aimed at this, but it’s postponed. I absolutely loved D since I first learned about it a year ago. And it's still the best choice for what I am doing with it. As a new user, I'm concerned about unfinished core language designs more than anything else. Frankly I have no idea how much DIP1023 will fix, but it may be a good idea to fix a part of the problem than do nothing.
- D as a system language. Sometimes I feel like this is being lost more people are advocating for being a higher level language. So it becomes hard to target esoteric platform without having to deconstruct the language and engage with doing weird stuff like copy paste druntime hook into a custom
object.d
. - Verbosity. Not being able to strip long enum type name makes it hard to write readable code:
MySuperLongFlagName flags = MySuperLongFlagName.SUPER_LONG_FLAG_A | MySuperLongFlagName.SUPER_LONG_FLAG_B | MySuperLongFlagName.SUPER_LONG_FLAG_C
Having to repeat the type name when you want to declare a static array makes code harder to read. - Not being able to have static array length inferred makes it super hard to get right, you either have to count the items manually, or put an arbitrary number, compile, and then use the number the compiler gave you..
- Although the language is pretty solid in most cases, I still feel that when dealing with metaprogramming, D is still lacking a lot. It feels quite inflexible, for example, I could not still find a way to log variables with its symbols, e.g,
loglnVars!(a, b, c); //Outputs a: 500, b: 200, c: 300
. The problem seems to be related to when using instance variables. This problem could be very easily solved if we had another kind of mixin template that all it done was literally copy/pasting code, like, even calling functions instead of only allowing declaration. I really want to reduce the friction I've been having with it. Even then, I still find myself constantly trying to do things the other way to make it work somehow. So, what I'm saying is that unlike the runtime code, the compilation time code is still too strict for my taste. My previous experience being with Haxe macros or even C++. bool
can be bothtrue
andfalse
. See Issue #20148.
import
doesn't verify module declaration. See Issue #15986.immutable delegate()
andimmutable delegate() immutable
are considered equal but treated differently. See Issue #16058.
- Output ranges are underspecified and poorly supported. It makes it difficult to represent things like files and buffers, and results in redundant code (see
sformat
andformattedWrite
instd.format
, for example) and awkward code likestd.outbuffer.OutBuffer
, which could mostly be a set of free functions instead. - Phobos is pretty rich and it honestly has most things I want, but
std.socket
is sorely missing astd.socket.ssl
submodule with support for both OpenSSL (on Posix) and Windows Secure Channel SSL. Maybe I'm in the minority, but I consider SSL/TLS support to be very core to a programming language and I am surprised that Phobos doesn't include any. I'm not saying we should reimplement SSL (as that is an objectively bad idea), but rather provide standard library-level access to system libraries already in-place. I understand why it currently is as it is,std.socket.Socket
merely being a convenience wrapper for C structs, but surely it is within the scope of Phobos to also wrap system SSL libraries? I'm currently using dlang-requests and Adam'shttp2.d
, and between the two I have something that kind of works, but it requires installing third-party OpenSSL on Windows which makes for a huge threshold. I did my best but it still requires the user to install a foreign.exe
and allow it to write to system directories. I'd throw money atstd.socket
Secure Channel support if there were a bounty for writing it. Community packages are all good and well, but it's obvious it's not a particularly popular itch to scratch, or there would be some dub package by now with the functionality I want. - The C++
std::vector
wrapper is not implemented on Linux. I'm working on things that would profit a lot from good C++ interop and this is one of the things slowing me down. - A need for something
std::unique_ptr
like in that it leads to a kind of destruction/invalidation when the wrapped object reaches it end of life, especially when the wrapper is emptied (e.g. null assignment). I'm spending time working on a convenience layer on top of the rather verbose and finicky Vulkan API and that API has very strong requirements for destroying API level objects. When wrapping them in Dlang GC managed objects, I need to use a kind of customunique_ptr
like wrapper so that it can call adispose()
method immediately when the tracked lifetime ends. This feels a bit too inelegant and error-prone, especially in combination with the GC that makes the destructor call order undetermined. My solution approach is somewhat borrowed from C#, but it is easy to use incorrectly and miss thedispose()
all when it matters. Honestly, I don't know how D can improve here, but it's been on my mind recently. - polished containers
- I think of ranges as a struct with 3 mandatory functions and some optional functions. This explanation will get you surprisingly far, nonetheless the
std
attempts to enumerate all possible versions of the interfaces such asRandomAccessFinite
with complex headers and several specialized implications. I think this is a failure; it won't always work so don't try; simplify the system, if an algorithm fails to compile with a strange edge case of a range; provide hacks, and make the code simple and readable so they can edit their own version. - Start the "D3 std" project, yesterday, with a distinctly flexible structure. If Adr says "I want to make a color lib", don't stand in his way give him the namespace
std.community.color
that can be written to his style guide, to his standards, on his github, and when a new version of the compiler ships a script will grab a snapshot. Give it a few months to see if the experiment plays out, if not delete lib from the std. - I would actually be in favor of splitting up the standard library into the actual library and some addon libraries that either get added when explicitly imported in the source file (solution might be hacks idk) or have to be added via dub, since it’s so simple it wouldn’t be a big inconvenience in my opinion and could maybe open the door for developing for embedded platforms in standard D.
- I'd like to have a support for dynamic imports in Phobos. I managed to do it with dlopen and other C stuff, but a cross-platform native solution would be better.
- While some of the Phobos APIs are truly amazing (
std.algorithm
<3) many are clearly a substitute for, or mapping to, C APIs. While we all appreciate C interop, it's arguable that the ease of integration removes the need to innovate in D, rather, relying on C libraries. Go, with the clunky CGo and green thread issues, led to many innovative native Go implementations. It would be nice to see native D libraries exposed to C ... (pipe dream?) For example,std.stdint
is juststdint.h
, so surely this belongs incore.stdc
only? With native aliases inobject.d
such asint8
uint8
rather thanbyte
/ushort
/ or C namespaced types likeuint16_t
. This makes it feel at times that D lacks its own identity and relies heavily on libc, rather than a more syscall driven approach and independent runtime (ala Rust). This is really visible in areas such asdirEntries
which has a random access range that falls apart upon multiple access withstd.algorithm
APIs, requiring unnecessary use of.array
in that context. In short, clunky APIs are imposed atop C APIs in the vein of being idiomatic and don't quite meet the needs. - D is the only mature language lacking idiomatic built-in asynchronous I/O support. While its true you can use functional APIs to read on a thread, the lack of built-in "promises" when it comes to I/O is somewhat disappointing. The stdlib contains fiber support, yet almost no part of D actually uses this.
- CTFE and templates are painfully slow to compile and are memory hungry.
- CTFE is too slow. I am transitioning back to using D after some Lisp projects, thus one reason I agree with Atila on very fast compile times when possible, and very fast CTFE.
- Any improvement to D compile times, possibly link times, is always cool. Sure, if the game compiles in 5-6 seconds, that's already very nice. But recompiling the full game using dub for 5-6 seconds after a single-line change, hm.
- A constant dread that looms over everything when I'm working on the project is the memory required to compile it skyrocketing. I don't feel like I overuse templates, but I don't hesitate to use them wherever they would simplify the code. Sometimes innocuous changes, such as adding a call to
std.concurrency.send
with brand new parameters, will suddenly bump the memory required by 100 Mb. Just from adding a function call, because it cascaded into a big tree of further template instantiations. 100 Mb doesn't sound like a whole lot, but combine it with some similar changes and it adds up. Currently a debug build requires some 3048 Mb, up from ~2850 Mb before recent changes of mine plus the addition of coloured dub output. At one point it was 8 Gb, before I made sure to avoid[std.conv.to](http://std.conv.to/)
with my huge nigh-to-one-thousand-member enum. Converting enum member names to strings is now done using a simpler template written by Stefan Koch. I'm not sure how much memory should be considered the norm, but I ran into concrete issues using CIs with free plans with hard memory limits. As in, "process killed" when it exceeded it. - A thing that sometimes comes back to bite me is compiler stack overflows. Some examples are Issue #18026 and and Issue #20562.
- My biggest problem right now is first and foremost is dmd not supporting DLL's properly. Foundational implementation details have not been focused on, and should have been solved 20+ years ago. Over the last 10 years, it has been very clear that we are losing people due to it. It prevents too many common use cases. Overall it feels a little bit insulting to see something so critical to not receive any attention... when something we don't really need like ImportC is then implemented. Why was it acceptable for OPTLINK to not produce a DLL without a linker script?
- dll support broken with dmd on windows
- I think long-term, the lack of parallel compilation and one-shot design of the compiler is going to be crippling for the language. D is designed to suck up lots of RAM because it will immediately release it. It has to do this because it needs all the speed it can get, because it can't multithread. Computers will not get much faster in single-core from here on out, so how fast D is now (which is fast, but not blazing fast) is how fast it's going to be going forward. There's no way to improve this either, because the compiler design is completely committed to mutating internal data structures at libitum. And since we're doing all that anyways, we might as well use the overgrown constant-folder called CTFE for compile-time code, since it's not like the horrible leakage will stick around for long. So the compiler design commits us to sucking: fast single-core BUT unparallelizable, high memory use that gets freed immediately meaning we can't make the compiler stick around and keep its cache warm, heavy mutation, which is fast, but prevents us from taking advantage from the ever growing advantages of multithreading. This in turn means that for multithreading we need to use library parallelism, forcing an internal split between DMD and Dub that is increasingly outdated anyways. (When do you really reuse Dub's library cache? Dub is a one-shot D compile driver in practice.) And because we're locked into all those choices, it will never get better. I don't have a good answer here.
- We have several mysterious memory corruption bugs in our software, and one of them could be traced to LDC Issue #4265. I don't know if there is any hope in getting that fixed, and until that time I can't be sure that the other bugs are our fault or not, or that this issue doesn't cause errors in computations that we haven't detected yet. It sheds doubt on the correctness of computations, which is very serious. That's why we think we should try to use DMD for production for the next few years, until we port all sources to 64 bit.
- ImportC isn't done yet! ImportC doesn't convert compile-time expressions into enums/constants. This is important because some C libraries define constants in their public interface this way, that they expect you to be able to use. See Issue #23513.
- TLS broken with -betterC
- Support for esoteric platforms in dub (e.g., Rust’s custom targets)
- Package namespaces for dub. It's difficult to fork a package and make it available. Naming things is hard, especially when you have to share a single namespace with many others! It also complicates adding support for things like dependencies in other languages.
- Finish the migration to GitHub issues. I think it's difficult to find things on Bugzilla, and I'm certain I'm not the only one.
- I think the community is to blame for wrong library design. Namely: the focus on generic libraries is causing harm. Generic libraries have worse names, ignore the problem domain, and open-ended public API without lots of boundaries. I think it's best to do more C-like libraries that can be used like everyone, like Mir, without too much templates, and with relatively boring classes + interfaces.
- I value the work that Ilya has done with the mir libraries, but it seems like he doesn’t feel like his ideas for D are taken very seriously, at least as far as I can tell.
- My interest in D is more related to data science. The types of things that are useful to me are being able to call libraries in other languages, being able to generate good charts, and some kind of REPL. My recollection is that a Windows repl for D depends on shared library support. So further work on that would be valuable. D has some packages for generating charts, but I don’t think new features are being developed on all and they may not be cross platform. This speaks to the ecosystem being stronger, which is difficult. On calling code from other languages, I think importC is probably a good thing here, but it would be nice to have some of the work related to R and Python more formally accepted into the language ecosystem, if they get to a high enough quality.
- Remove style/whitespace checkers, replace with automatic formatting & committing back into PR branch. No more random style based errors in CI (some are hard to figure out).
- The biggest flaw of D in my opinion is the ecosystem (access to libraries/frameworks). Of course there are some C library bindings but they are annoying to set up and always feel like a hack, not like native support. I like to develop programs with a GUI (including stuff like SFML because it’s technically a “Graphical User Interface”), obvious reasons being the better way to grasp what you achieved and the possibility to make actual modern utilities. Many of the bindings to C libraries are either hacky or unmaintained, nothing really feels polished or official. Additionally, unmaintained D libraries make the community feel rotten, like the open ecosystem is dead and you’re the only one trying to program in D. According to the official Dlang page that is not entirely true, since some companies use D in some parts of their software (or have used it at some point at least), but that rarely adds anything to the open-source side of things and leaves you thinking you’re the last person on a sinking ship.
- D lacks tooling. This part is probably one of the biggest problem to bring D in a company. Sure, for experienced developers, this has probably no impact (especially if they come from C/C++). But if they come from the .Net/Java world, those developers expect IDEs or great tooling experience. It is even more important for people with a limited background. D is probably superior to C# (but for how long) in features, but the tooling support for C# is so much more important and mature that it is still feels more productive to write C# code than D. This is a sad reality in companies where developers don't come from a systems programming language background.
- While not every language needs it, I feel like the D ecosystem needs some more standardization. What I mean by this is that often times I'll need a database driver, or graphics library, or message passing library, and from what I can tell, there is no community-chosen standard for any of these things. That makes it hard when I have to justify the time I'm spending on things, and I can't just spend a few days playing around with all the different solutions. I think the community needs to organize a bit more and create a few extremely high-quality libraries and development tools, instead of having 20 different options that aren't very good.
- The only idea I have to bring some attention to D is to make Trinix a reality (or somehow else get D into the Linux kernel space, someone already made a driver in D, if I remember correctly he did a talk on that on some conference) to spark interest of some of the kernel developers there, though that probably wouldn’t help much with high-level library support, but it might strengthen the general adoption and awareness of D. Either way, I think attention would be the best way to heal Dlang.
- Dub issue #2229 blocks us from upgrading Dub. Since Dub is distributed with the compiler, it also kind of blocks us from upgrading the compiler easily (I know I could work around that). It definitely keeps us from benefiting from my own PRs that got merged into Dub after the introduction of the regression (one of which fixes a blocker for us).
- A built-in Language Server for IDE integration (like "gopls"). The whole toolchain to parse D source code to an AST, the language server, etc, should be part of the standard toolchain/reference compiler. This means that developer experience is prioritized (the most important language aspect) and works OOTB, and that others can build more tools like static analysis on top of the reference libraries. It would be nice if it could automatically generate and infer D definitions for C files used in the project behind-the-scenes, so that autocomplete and type-checking are available for them the same as if you DID have a generated D file with "extern (C)" definitions.
- Could be better if there was some kind of compiler daemon for faster compilation times. About a better detection on what changed, I don't know how much feasible is that. though I think that prolly would depend a lot on having real support to .di files. CTFE-cache is still a WIP thing which could really help a lot too.
- A built-in, very opinionated formatter (like "gofmt"). (Optionally) Linting would be nice to have.
- A standard tool to convert C headers to D definitions, like Zig has "translate-c”.
- D sometimes just crashes on exit with daemon threads (Issue #19978). It's possibly the worst open D bug I know of, since it's both intermittent and fail-silent.
- Testing and unit testing in D is a little cumbersome. I do appreciate inline unittests for small things, but there's still a need for integration tests, and usually, I have to do this by making a separate dub project for that, which isn't ideal. I'd like if dub could include a tests directory or something of that nature, where modules containing only tests could be defined. Unit test assertion failure messages are also very annoying to read, and it usually devolves into me adding log statements in order to debug, whereas in JUnit or pytest, if the test-runner encounters an assertion failure, lots of well-formatted details are printed to stdout so it's easy to see what's going on.
- Fragmented ecosystem. We try to keep with the latest emerging practices such as
@safe
+ DIP1000, however, it makes it virtually impossible to use other modules on code.dlang.org without wrapping everything in@trusted
lambdas. - The test suite, at least the one for Phobos, is cumbersome. It takes a long while to build, making it entirely possible the contributor does not bother to wait for its results. and quite often it has random failures, or at least had a few years ago. This creates needless feedback cycles, which are very slow since we're based in different timezones and have different contribution habits.
- Currently D is "every person for themselves" with very little module reuse witnessed, users relying on forks of forks on GitHub due to disappearing maintainers, etc. In short, a lack of cohesion creating an impression of a poorly maintained ecosystem.
- Unfortunately the tooling story around D is not great. It's not bad specifically, however memory profiling tools are completely dead upstream, so GC and profiling are just non options. Go excels in terms of GC profiling, and Rust has extensive tooling for understanding program flow, conditions, etc. D could really shine here by illuminating runtime behaviour of the GC (and beyond) to allow us to optimise and tune applications. If anyone has tried using perf or callgrind in combination with vibe.d - you know the pain.
- While dub is far better than meson for building D projects, in terms of system integration it leaves a lot to be desired (lack of setuptools style installation options for additional files etc)
- Dub support is bad. Should put the library next to the project and then import it into your personal project, so that you can use the usb if desired. Right now it writes to the userspace, which I do not want that to happen.
- As Adam has been saying for a while, the
-i
switch is powerful, and largely eliminates the need to use Dub. This is true. I used to use Dub for smaller projects with dependencies (those involving only D code) but Dub no longer brings much to the table there. What I'd like: It would be nice to go into a project directory, run a command, and have a copy/symbolic link of all the D files for the dependency in the correct subdirectory so that it works with the-i
switch. I do that manually, but it's inconvenient. The symbolic link enables automatic updates of the dependency. The copy is for when I don't want automatic updates. - I wish Dub would create import libraries for Windows. I don't know what that would require, but it would be a great help for those of us that don't normally use Windows. Even better would be hosting import libraries on code.dlang.org, or having an online option to create them, similar to the way we can use run.dlang.io to compile code. Then I wouldn't have to mess with that process at all.
- My boss just came across a broken link in my docs and the reason is ddoc. So ddoc automatically highlights any name that happens to be in scope at the time. This is completely useless, so it is suppressed every single time by prepending a _ to the word. This is a mess that complicates doing anything with the ddoc source and is liable to break things at any time; another parameter getting renamed can now break links. I'd really like to kill that useless misfeature.
- Language server is getting better and better these days, so I want to give a shoutout to the serve-d contributors (I tried to contribute too!), but is lagging being other languages (mostly when it comes to D specific features, templates), templates is hard to support, so hopefully in the future, the DMD compiler could be used to provide types on the fly as a service, without generating any file (perhaps reusing what it does to print ast stuff).
- Poor debug support. Generates poor debug information or even no information at all. Do not want to resort to spam print just to see the current value Inferior to Visual Studio Debugging support for C#.
- Debugging still is causing problems.. can't see globals, can't understand D's types..
- I believe dub could really get a target type which builds all static libraries dependencies and a main static library. I have been running all the way around over scripts to simulate that, and I lose debugging information in that process. If this were officially handled by dub, I doubt I would be suffering from that. This is an alternative when it is easier to use a static library rather than a dynamic library (or even the only solution in case of PS Vita).
- My wish for D would be to have an updated C++ interop page. It would be nice to have every outdated spec/doc page updated, if there are any other.
- Change phrase 'dynamic array' to (suggestion) 'access'. The result of slicing is surely just creating a path through which [possibly a subset of] the target item can be manipulated. IMO, 'access' is a less misleading name for such a path than 'dynamic array'. Related thread.
- Our biggest concern is the lack of proper documentation in general. Oftentimes, it's not that the documentation doesn't exist, but that it isn't very well made. It can be very hard to learn D when the resources that should help one learn the language simply aren't easy to find and/or understand. This concerns us greatly because then the formation of D users falls directly on the community's various chat and forum platforms or in the case of our group, it means we have to put aside time to teach new developers ourselves. This makes recruitment especially problematic as we have a few people who would like to join our team either for this project or future projects, but we do not have the capacity to integrate these people into our team due to the lack of documentation.
- There aren't many resources for complete beginners; this is also hurting D in our opinion as most people tend to stick with the language they learn first.
- Some more documentation content in the style of "The Rust Book" or "Ziglearn" that is practically-oriented would be good. Basically something longer than "Tour of D" but not purely technical like the reference/standard docs.
- I think that D desperately needs better documentation. Phobos is generally easy enough to navigate, but still I would like to see more examples for many things. But I think that a significant effort should be made to improve the ddoc generation to produce static documentation from code that's as good, if not better, than Javadoc. I've noticed with some of the libraries I've published on dub, that those with very extensive, verbose documentation tend to do better. I usually write my own docs with Vuepress or some other site generator tool, but the vast majority of libraries just rely on the standard documentation generation.
- The general "L&F" of the project is rather dated, painting a 90s niche air around DLang. Unfortunately this helps reinforce the idea that DLang will always be niche. An uplift to the web presence, as well as a more welcoming and community-centric code.dlang.org would help significantly.
- I read that cross compilation is possible a long time ago but couldn't find any doc on it. If some doc on it does exists, sorry for not looking hard enough. If none exists, it would be nice to have some doc on this, I feel like this is an important thing for a modern language.
- I could not find an image library and thought it didn't exist. In hindsight this sounds dumb, there are plenty of image packages, however in my beginner's mind, as well as being in a hurry it was a very easy mistake to make. I think an easy fix for this issue in general, is a page on dlang.org showcasing projects, as well as on the front page, similar to the Odin website, or the blender foundation showcase reel: https://www.youtube.com/watch?v=QRqY_20ti9A. It ensures new users know that D can do anything in a nice way. (This could be difficult to organize, but if you find a good way to do that I think it could work really well, and I do think it would have helped me when I started, to see things others have made.) I have seen myself make the mistake above as well as other people, perception is a powerful thing.
- Documentation with examples for using D to create Windows apps that have dependencies on DLLs, and how to distribute those apps. Maybe that already exists. I have not found it.
- A document outlining precisely what importC and betterC will look like when they're done. Particularly for importC, I have no idea what the end product will be, beyond "compiles some C code". It is not currently in a state where very many things compile if they use the preprocessor. It would be nice to have a list of goals like: SQLite will compile, Geany will compile, etc.
- Forums that aren't welcoming to toxic people. The only path to true neutrality is to get rid of everyone else, which neutrality policies tend to do. The current policy has led to a forum full of naysayers, who will eventually also leave once they're bored.
- We do have some circle of negativity in the forum. I feel it has gotten worse, well maybe not during the last few years but when compared to 2015 when I started reading it. A clash or rant every now and then does not push people away, but the problem is the threads degenerate into an overall negative atmosphere and that's what does drive people away. I think we need some sort of social mechanism that could make those threads to reblossom, but I'm bad at people things so I'm not sure what it would be.
- This is not a big gripe, but discussion of gender pronouns should be allowed at the forums, since it's an issue that affects the language (what language is okay at the docs/forums). I do agree with the no-politics line when it's something that D does not deal with, such as Invasion of Ukraine or Native American affairs.
- Code of Conduct Policy. While I know it's less fun to talk about, I'd like to suggest adding a code of conduct or at the least a point of contact for handling any issues that arise. I think some of the prominent C++ conferences are really taking some heat for their lack of initiative, enforcement, and transparency in this area. e.g., From last year many folks from the C++ community (and myself) were quite shocked at how this situation was handled (or rather not handled) (full thread here). There seems to be even a lot of folks leaving C++ over this. Here’s an example Code of Conduct. Perhaps form a code of conduct based off of the Python code of conduct, or other conferences. Perhaps there is someone who can be consulted (or be available online) at the least during the conference as a 'code of conduct' team. In the unfortunate event that something happens, it's nice to have some system in place to take care of these things and get folks the care they need. I think other industry folks from the C++ community, academia, students, etc. can more confidently attend in case they have any worries. And just to be clear, the online and in-person D conferences have been wonderful in my eyes so far, and no such issues have ever occurred as far as I know. Just wanted to be a bit pro-active :) Obviously I can try to help send more examples if you think that'd be helpful.
- In the D dlang Forum under ecosystem a "miscellaneous" heading. I would like the dlang forum to provide a way to discuss/ focus on tangential issues that are unlikely to be of interest to the wider community for the development of the D language itself (long tail interests/ecosystem/infrastructure). I think I am looking for a miscellaneous section under ecosystem in the forums, so I can keep out of the face of general D users with related but rather esoteric matters of interest (that might otherwise not be welcome as being too specific a side interest). As an example of what I might use it for with less hesitation: I could post things D related that are specific to Nix and nixpackages that I know are unlikely to be of wider interest.
- In the D Forum a way to support org mode markup. I understand that there are likely to be issues (technical, time and manpower, and social/political, and whether it is of (sufficient) interest) and that this might not be straightforward. It might be enough that an email submission in org-mode markup is recognized (by DFeed) as something not to be processed and left alone as ordinary plain text, rather than any attempt being made to prettify it in html. Org markup (like markdown) is visually pretty clear. (To be clear) I am interested in original org-mode markup text, which can be re-used and developed, (rather than org-modes ability to create htmlized email).
The feedback in this section was sent to me in article/essay form. It's more valuable to publish in full rather than breaking it down to its points.
I don’t want to be discouraging of good work, but D is not lacking in great features, it is lacking in its implementation of the basics.
I have come to believe over several years working in D, managing work in D at some scale (10s of devs, not 100s) & advocating for D that the foundations are shaky and crumbly and need work.
While it is not possible to implement a struct as drop-in replacement for a built in slice, while template symbol emission bugs keep happening[1], while the built in AAs are not in great shape (and the signature of toHash is a PITA), while the compiler is a huge memory hog and compile times for templates get wild, while speculative compilation results somehow go wrong and leak in to the non-speculative parts of compilation (e.g. https://issues.dlang.org/show_bug.cgi?id=19545), while syntax changes happen without enough noise (so even basic tooling ends up breaking), while shared and property and synchronised classes and so on sit in poor and/or incomplete shape, while delegate contexts still have qualifier problems[2]…
Why would the limited resources available be focused on a built-in sum type?
D is an amazing language. “Another killer feature” isn’t the missing piece to it getting some real, persistent, large-scale traction. They key is the rock solid basics and the cleaning up of lingering nonsense. Then the features can come, if they need to, because everyone loves building features and the more the basics are sorted out the easier it will be to add more.
The really committed and talented people here need to choose quality and build it.
I think D has a culture of accepting all sorts of badness while promising greatness, which is self-limiting.
I have poured a unbelievable number of hours in to D over the years, both commercially and open source, it has formed the backbone of my career, I want to see it succeed, but this will not happen if the basics are not dealt with.
I’m happy talk more about this with any of the core developers, I may not write a lot more out here as I don’t want to keep ladling on negativity in public, but for a variety of reasons I think change is needed.
[1] please no “where’s the bug report”, it’s whackamole. There needs to be a reckoning with the fundamental nature of the problem. Does anyone even understand the current design & implementation?
[2] this is pretty much what I could think of off the top of my head. I’m sure there’s m
First D has a product market fit. People have built useful things in D, have been attracted to it for its feature, many of them unique in the PL space. So why don't they stay? Or why is it challenging to move an already big machine to D?
The main problem is quality of implementation. I can delve in almost any area of the language and find that the implementation is just Jenky, even when it work (and often, it just doesn't work). Let me provide a few exemples, but keep in mind these are exemple and this permeates the whole D ecosystem. For instance OOP. OOP works in D right, there aren't that many bugs reported about it and all in all, that seems like a part of the language that actually works properly. Well yes, for as long as you don't open the hood. The implementation is just jenky. Consider:
- One needs to go through 2 indirection to get to the typeid, when it could be inline with the vtable.
- One needs to walk a linked list to do downcasts when it can be done with one bound check, one load and one compare.
- When downcasting to a final class, comparing the typeid is all you should need, yet, the linked list is walked again.
- D goes for virtual by default - which is IMO the sensible default - but this is bound to be terribly slow unless there is a devirtualization pass in the compiler, which can only happen at link time. Yet LTO is not intergrated into the toolchain.
- in contracts are dynamically bound rather than statically bound, which is incorrect.
- and much more...
Second, leaky design.
Not so long ago, i was discussing with an ex D programmer (huho) why rust program never seems to grow past a certain size. The reasons is that rust's type system is very leaky about implementation details, which make these very hard to change. Once the application grows past a certain size, so of its core component are bound to become unfit, and the cost of changing them becomes prohibitive, hence the application stops growing. A concrete exemple would be to replace a value type hashmap with a copy on write one to improve perfs. This is possible in C++ for instance. But this isn't in rust, because the internal accounting will have an impact on the ownership at the API boundary, which in turn make mens changing the implementation detail of the hashmap require to change it everywhere it is used too.
Early D design decision avoided that problem by qualifying observable behavior. For instance pure, do not prevent you to mutate things internally, but will enforce that it is done in a way that is not observable from the outside. More recent attributes, such as @nogc fall into this trap. This in turn cause headache for any large project because expected attribute clash due to implementation details all over the place. This is fundamentally untractable for any largish user.
Third, the boat-plane problem.
D's leadership in unwilling or unable to make decision about the direction of the project. Is D a boat? Yes. Is it a plan? Well, let's just screw wings on the side of the boat and voila, it's a boat-plane, but really, what it is is a shitty boat that is also a shitty plane, and overall it is good at nothing. To the contrary, D needs to make decisions for itself and use them to cut through the design space as far as possible. I presented one exemple already: virtual by default and LTO. There are just many more:
- D has a GC and D wants to promote safety, therefore @nogc 's current approach is a non starter. What one wants is to allocate everything on the GC and explicitly free (or not). this has design implication for the GC itself.
- enums are closed set for final switch, but open set when used as C flags. They can be either, but not both.
- type qualifier support vs templates. They simply don't mix. We either jettison one of them, or we make them work together (probably the sensible path forward).
Fourth, the shinny object problem.
The D community, and its leadership seems to always want to reach for the next thing, which will, we are assured, going to be a game changer. Reaching for the next thing is what project do when they try to reach market fit. D reached that point 10 years ago, and should have pivoted then. The next best time to do so is now. The shinny object don't bring much value to D users, but it has numerous deleterious effects on D:
- Constant tooling breakage. noreturn, new contract syntax, throw expressions, body => do, and so on are all changes that are nice to have, but change D's syntax. Which means it break tools all the time. The result is slightly nicer syntax, but a complete absence of tools (D tooling is in fact often worse than C++'s, let alone any properly tooled language such as JS, java, C# or whatever).
- Numerous bugs. People are hit, have to diagnose and then find workaround for bugs shipping with feature they never asked for. This is not theoretical, currently, symmetry is using a custom build of DMD, because NO PUBLIC RELEASE can compile its codebase at the moment due to 2 bugs: one related to DIP1000 - which we do not use - and one related to the attribute soup proliferation.
- An explosion of dialect in the languages. These feature often are not thought through to form a cohesive whole, so they end up not being usable together, de facto creating fragmentation within the language, and as a result, within the user's codebase.
I hope that helps. I also hope this can stir things in a more positive direction. tuples, sum type, or whatever the bullshit of the day isn't what's going to help D at the moment. It's like putting a better sound system on a car that has no wheels. Symmetry can put some ressources to help on that front, but, without support from D's leadership, I don't think this will work. And TBH, Walter might need an intervention on the matter, because if nothing changes, we'll have one more ex D user.
A lot of the issue I mention above are not very big nor very hard to fix, but there are so many of them that thing get out of hands. If D is to work sustainably, we need to churn through enough of them to reverse the tendance. This is not hard per se, but this is work and, most importantly, require focus - which I think is the ingredient we lack at the moment.
So what about a weekly sprint focused on one specific problem? I can pick the topics and do coordination if we need someone to do it. I think I'd be good at this, but idk if I have the social capital to get people onboard by myself.
I want a language that isn't d, but is near by to d. I want the direction to be more high level, not more c/assembly level. I fully acknowledge that is not my choice and i'm fully okay with that. The consequence is that i don't invest much time into actually improving the compiler, ecosystem, libraries, or would write future projects in d. That said, the thing that is exceptional is that d has some amazing individuals in the core community. That is what i enjoy most and keeps me joining beerconf and following the conferences. Specific individuals are mike p, steven s, adam r, ali c, and iain b. In many ways, these are the front lines of public d. I also value walter, atila, andrei, leaeth, john c, and the others that make up the ecosystem. I know there are key individuals managing the code, but less familiar with them. Everyone has been extremely kind, professional, and patient when i've interacted with them.
The "@safe by default" and "bool" dips discussion and conclusions were where my realization/clarity that the direction of d was not aligned with what i was desiring in a future language. I realized that i want a language with much stronger correctness guarantees. For me, i think this comes from something that is based, or traceable, to category theory or lambda calculus. Basically general purpose functional programming, but in a procedural syntax. That probably isn't possible with the c heritage and desire to adhere to c'isms.
The thing that i think would help d the most, is to define its identity, and not with a slogan. A good start would be to specify what the primary platform1 is, what the primary application2 area is, and who the target audience is. Prioritize improving the quality and the experience here first. In my opinion, d advertises itself as a systems language, but really, is kind of a lousy systems programming language. The reason that i say this is if i'm really bit banging on a device driver or embedded system, i really don't care about phobos, but phobos is where d really shines. If i want a "betterc", i'll use a c++ compiler with a linter and static analyzer.
From my perspective, as it stands today, the realistic target audience is running linux and is a:
-
Hobbyist that enjoys tinkering with compilers and community that talks compiler/language lingo.
-
Student learning programming. If you stick with the core, d is a great language for learning. It will make one a better programmer and the learning curve is quite gentle compared to other languages.
-
A very advanced small team that is going to write their own code and probably maintain their own fork of compiler or atleast has the chops to be able to.
That is an incredibly small market/audience. Windows developers should not use d as there is no . Net support and c#/f# are better supported and more pervasive. Java platforms have their own supported languages and ecosystem etc.
The core audience needs to be defined and an honest assessment of how well d is meets that audience's needs. Be brutal in narrowing this audience definition.
As an example, a place i used to think d would be good for is maintaining a legacy c library. In order to do so, d would need to be able to produce an abi 1:1 replacement for a shared/static library that could be put in a distributions packaging system with no impact to downstream consumers. After converting a few c codebases to d, i'm a lot less convinced of the added value of using d in this way. 1) it's trivial to do the initial mostly 1:1 conversion (kudos to d on this). However, going from converted c to d code to idiomatic d is an incredible lift. If the maintainers want to do that, they will be rewarded but including the druntime probably isn't acceptable to downstream package consumers and it basically changes the product. This ends up being a useful feature for the dedicated advanced small team case.
Another subdivision of the audience, to think about, is who is desired to contribute to compiler development. I'm a pretty knowledgeable and decent programmer, but dmd is something that i cannot grok with a couple of weekends. If the barrier to contributing were reduced, it might be more approachable for broader contributors. I realize that comes with its own set of other problems though too.
In summary, quality starts at the top. Be specific about what quality means and what platform, application, and audience is the core one, and focus on improving the quality and experience for them.