May 11, 2022
On Tue, May 10, 2022 at 11:08:18PM +0000, Joshua via Digitalmars-d wrote: [...]
> I [can't](https://mesonbuild.com/Rust.html) throw Rust into the same build target, but even if I could I'd still have to deal with the fact that doing anything interesting in Rust (or Go) requires using Cargo (or `go get`) to download 10× more dependencies than I asked for, which is 10× more long-term instability than I intended to accept.

Yeah, that's one big factor that turns me off most popular "new" languages these days.  I don't *want* tons of dependencies that I know nothing about. I want the minimum to get my job done, and that's *it*. Anything that requires a big hairball of dependencies is a no-go in my book.


> I don't mean to be excessively critical: they're wonderful languages, and having the option to reuse work from such large ecosystems is _truly amazing_. AFAIK, nothing remotely similar existed for compiled languages more than 10 or 15 years ago. I'm just not a fan of the trade-off: it's like, _"Everything you can see in this vast ecosystem is free to reuse, all you have to do is use this here build system which supports the only programming language you'll ever need. Isn't that great? Now go forth and make a name for yourself by rewriting useful libraries from other ~~other~~ inferior languages into our new paradise!"_ It's exciting and fun and so much work and at the end you get... a silo. Not so with D (or at least not as far as I know yet! ☺)

This is one reason why I'm still not sold on dub, despite having used D for a decade.  I just don't like its walled garden philosophy.  It places arbitrary limitations on what is essentially an algorithmic solution that applies to far more general things than its authors deemed worthy of recognition.  This is why I wrote what I did recently, about busting dub out of its own walled garden.  Don't know if I'll succeed; but in the worst case, my last-resort secret plan is to write a general build tool that can read dub configurations and process them without any effort on the part of the package authors, so that I can import dub projects without ever using dub.

As for D itself, its ease of integration with other languages has been great.  It integrates with C basically seamlessly -- recently I've been working on a project that uses libxcb, and D lets me declare xcb prototypes on an as-needed basis: I don't even need to convert the entire header file, just port over those functions that I actually use and I'm good to go. And where conversion of entire headers are necessary, tools like dpp are great.  C++ integration is a bit trickier (some parts aren't 100% compatible, so I heard -- haven't tried it myself). But Java integration with Adam's jni.d is awesome.  I've also used D's metaprogramming capabilities to reduce the amount of boilerplate needed to interface with GLSL shader code, and that's been great too.


T

-- 
Only boring people get bored. -- JM
May 11, 2022

Others have spoken in this long thread about why D is not more popular than X, where X=Go or Rust or what have you. I don't have much to add to this, other than to observe that Nim is good work and hasn't exactly taken over the world and, like D, it doesn't have a major corporate sponsor.

I can only speak from my personal experience. I'm in the process of completing a project to port about 9000 lines of C I wrote 10 years ago to provide me with tools to manage my finances the way I want to. I'm a very experienced software developer and project manager, now retired. I'm certainly out-of-touch with the way programmers work today, but I am very familiar with contemporary languages as a result of this project, as well as a long-standing personal interest in programming languages.

As I observed in another recent post, I considered and rejected Rust, Go, Scheme, Haskell and Nim for this project and chose D. A few comments on each:

  1. The main application of my project makes heavy use of gtk and sqlite. In Rust, gtk callbacks are required to be "static", meaning that the closures you pass to the signal connection routines must not make any free-variable references that are not static (don't live as long as the program). I will spare you the details, but if you are using sqlite in those callbacks, a necessity (all the work is done in the callbacks), I contend that there is no way to avoid using "unsafe" Rust code. The Rust community, like D's, is helpful, and I've discussed the specifics with them in gory detail, and no one has come up with a solution to the problems I've encountered, nor have I and believe me, I tried. If I am going to be forced to write unsafe Rust, why put up with all the borrow-checker, lifetime-checker pain? Rust's goal of memory safety without a GC makes we the programmers part of the memory management system. Add to that very long compilation times right in the middle of your edit, compile, debug cycle and it's just not worth it.

  2. Scheme is a great language and Chez Scheme is a fine implementation. It's mature, well documented and very fast. I use Scheme for a lot of things. But this project is large enough that the dynamic typing becomes a liability. Too many issues that would be caught at compile time with a static language turn into run-time debugging adventures. There is also an issue with weak type-checking across the foreign-function interface (e.g., all pointers look like void* pointers to Chez, so you can pass the wrong one to C without complaint from the Chez or C compiler).

  3. I could have done this project in Go and I'm sure it would have been fine, but I chose D instead based on my preference for the language. The tradeoffs weren't all that different so it came down to personal preference.

  4. I can say the same about Nim -- personal preference. And there is a fair amount chatter about compiler bugs on the network that was also a bit off-putting.

  5. Haskell is another great language, but the nature of how gtk works forces you into maintaining a fair amount of state the old-fashioned way, rather than passing new state with function calls. If much of your code is going to be old-fashioned imperative, why choose a functional language that has had imperative capabilities glued on?

This brings me to my D experience. It took me a while to learn where the land-mines are. The big one was passing a pointer to C that originated on the D side and then getting burned by the GC because I hadn't retained a reference to the object. It took a long time to debug that one, with help from this community. In hindsight, it would have been a lot simpler if I'd read the warning in the toStringz documentation that spells this out. Someone in this thread said that the GC makes C interaction difficult (I forget the exact phrase used). Nah -- you just need to know about this issue and take care to protect objects that originate on the D side. If they originate on the C side, no problem.

But once I got comfortable with the language, the porting of the C code went fairly quickly and the result is just what I wanted: much more concise, readable (and therefore maintainable) code the performance of which is indistinguishable from the C version (truth be told, most of the heavy lifting is done in sqlite, so I probably could have written this in Python -- ugh -- and gotten acceptable performance). I like being able to debug with gdb when runtime problems do arise and I appreciate the fast compile times. After all, the edit-compile-debug cycle is the inner loop when you are developing.

Overall, I'm very impressed by D. The compiler seems solid, the library functions I've used have all worked properly, and the documentation is mostly good. I think the criticisms that have been directed at D about lacking vision, blah, blah, have been from those who have not used it to produce working software that does what it is supposed to do with good performance. In other words, usable in practice (recall that Einstein said "In theory, there's no difference between theory and practice"). That is the ultimate test and at least for me, D has passed that test.

/Don

May 11, 2022
Thanks, Don. I really appreciate you spending the time to write this. It's quite an enjoyable read! I'm glad D meets your programming needs.
May 11, 2022
On 5/9/2022 9:16 PM, Joshua wrote:
> Lately I started looking at compiled functional languages that integrate easily with C because I expect I’ll need their expressiveness and type safety for some tricky data transformations.
With ImportC, D is getting pretty darned good at integrating with C.
May 12, 2022
On Thursday, 12 May 2022 at 00:10:00 UTC, Walter Bright wrote:
> With ImportC, D is getting pretty darned good at integrating with C.

Still not as good as it already was without it.

http://dpldocs.info/this-week-in-d/Blog.Posted_2022_05_09.html#importc
May 11, 2022
On Wed, May 11, 2022 at 05:10:00PM -0700, Walter Bright via Digitalmars-d wrote:
> On 5/9/2022 9:16 PM, Joshua wrote:
> > Lately I started looking at compiled functional languages that integrate easily with C because I expect I’ll need their expressiveness and type safety for some tricky data transformations.
>
> With ImportC, D is getting pretty darned good at integrating with C.

Even without ImportC, I already integrate with C well enough.  I've been converting C prototypes to extern(C) declarations on an as-needed basis (as opposed to translating the entire C header), and it works pretty well.  Thanks to pragma(lib), I don't even need to change my build script; the compiler automatically pulls in the library for me upon importing the converted D module.

The main hurdle of ImportC that makes it not as attractive as it could be, is the lack of an integrated C preprocessor. Meaning, I have to manually invoke the C preprocessor before ImportC is useful. That pretty much nullifies the value of ImportC: I might as well just translate the C prototypes myself and it'd be less troublesome.  If ImportC were to reach the point where I can literally just import any system C header, *without* needing to run the preprocessor myself beforehand, *that* would make ImportC immensely more useful in terms of C integration.


T

-- 
If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...
May 12, 2022

On Thursday, 12 May 2022 at 00:12:05 UTC, Adam D Ruppe wrote:

>

http://dpldocs.info/this-week-in-d/Blog.Posted_2022_05_09.html#importc

No, I think ImportC is a good idea, just like unittest and external test libraries.

I also think d should link to the library of C++. so that d users can directly use C++'s functions or libraries . Similarly, d should also link to Rust.

Their ecology is relatively large, so we should make use of it . Let theirs are mines.

May 11, 2022
On 5/11/2022 5:12 PM, Adam D Ruppe wrote:
> On Thursday, 12 May 2022 at 00:10:00 UTC, Walter Bright wrote:
>> With ImportC, D is getting pretty darned good at integrating with C.
> 
> Still not as good as it already was without it.
> 
> http://dpldocs.info/this-week-in-d/Blog.Posted_2022_05_09.html#importc

You should mention that ImportC supports C constructs that are not expressible in D, such as _Generic and bitfields. (Although I added bitfield support to D recently.)

> And what could have been done to D itself in that time?

C interoperability is a major barrier to using D. ImportC is probably the best leverage for D among existing initiatives.

> translating those files wasn't that hard and now it is done

The trouble comes when those header files change, you've got to figure out what changed and update those hand-translated files. This is a big win for ImportC.
May 11, 2022
On 5/11/2022 5:53 PM, H. S. Teoh wrote:
> The main hurdle of ImportC that makes it not as attractive as it could
> be, is the lack of an integrated C preprocessor. Meaning, I have to
> manually invoke the C preprocessor before ImportC is useful.

I know. dmd now invokes cpp automatically for Posix systems, cl /P for Windows coff. A PR invokes sppn for Win32 omf builds, it's all green:

https://github.com/dlang/dmd/pull/14090


> That pretty
> much nullifies the value of ImportC: I might as well just translate the
> C prototypes myself and it'd be less troublesome.

Wouldn't adding a make rule to run the preprocessor be just a couple lines of make?


> If ImportC were to
> reach the point where I can literally just import any system C header,
> *without* needing to run the preprocessor myself beforehand, *that*
> would make ImportC immensely more useful in terms of C integration.

I agree. Now, if only someone would approve 14090, we'd be good to go!
May 12, 2022
On Thursday, 12 May 2022 at 03:43:50 UTC, Walter Bright wrote:
> You should mention that ImportC supports C constructs that are not expressible in D, such as _Generic and bitfields.

I've been using D for 15 years across a variety of applications, including making drivers to interface with esoteric hardware. Those have never been useful.

C bitfields are useless even in C for hardware work, unless you lock into proprietary compiler, since the layout is undefined. You're much better off just taking out the spec sheet and using the | and & operators.

> C interoperability is a major barrier to using D.

D is very good at C interoperability. You have a bad habit of spreading misinformation about D. Why would someone use it if its own creator thinks it sucks?

But in reality, D is a very good language that makes accessing C code very easy.

> The trouble comes when those header files change, you've got to figure out what changed and update those hand-translated files.

That's not really hard when they change in one place. You can do cherry-pick merge and be done with it in little time. Stable APIs are a very small investment with big returns in D.

It is hard though when you are trying to match the version on the user's computer, since dstep's 99% translation may not be good enough and a pre-made packaged thing may not match.

This is where importC can win - matching what's on the build system automatically. It isn't there yet though.