digitalmars.D - C is Brittle D is Plastic
- Walter Bright (35/35) Mar 21 It's true that writing code in C doesn't automatically make it faster.
- Dennis (21/23) Mar 22 Another example where D shines in this regard is UFCS allowing
- Sergey (5/7) Mar 22 Some languages consider this as a downside. Because of clarity
- Kapendev (6/13) Mar 22 The same can be said for replacing the `->` operator with a `.`.
- Sergey (13/18) Mar 22 This is wrong example Kap.
- Quirin Schroll (7/14) Mar 25 That’s an odd take. C# and Kotlin have properties since day one
- Walter Bright (1/1) Mar 22 Nice example!
- Quirin Schroll (3/26) Mar 25 That isn’t UFCS, that’s just empty parentheses being optional.
- Derek Fawcus (21/31) Mar 22 Not really, if one has a little for-thought, and commits to
- Derek Fawcus (13/19) Mar 22 One can even play macro games (using _Generic) to make a wrapper
- Lance Bachmeier (6/14) Mar 22 If that's the standard (unlimited time and resources) then it was
- Walter Bright (14/23) Mar 22 If _Generic is needed, you have outgrown C. (I am regularly baffled by t...
- Richard (Rikki) Andrew Cattermole (6/9) Mar 22 Its not like we can talk, we've got some real uglies hiding out in our
- Lance Bachmeier (9/13) Mar 22 I recently watched a YouTube video about how LLMs produce almost
- Derek Fawcus (19/22) Mar 23 In the example I cited, that was not an issue. I was able to
- user1234 (7/10) Mar 23 Yes from the user POV. From the compilers-details POV I think
- Walter Bright (15/26) Mar 23 I admit the implementation code is not a dreamboat. But in defense, in t...
- Richard (Rikki) Andrew Cattermole (2/4) Mar 23 Did you ever study IBM CUA?
- Walter Bright (2/3) Mar 23 I had the book but never read it. It came out years after my attempt.
- Richard (Rikki) Andrew Cattermole (6/10) Mar 23 I've got it as well, the last of the series I think it is.
- Walter Bright (3/17) Mar 24 I sold the book (!) because I wanted to focus on other things and the bo...
- Richard (Rikki) Andrew Cattermole (2/22) Mar 24 Oh lol, its cheap now and also on archive.org.
- Max Samukha (2/4) Mar 24 Again, not everybody likes it.
- user1234 (5/9) Mar 24 I don't know what this "2-phases lookup system" is refering to
- H. S. Teoh (23/33) Mar 24 In the beginning, D's symbol lookup mechanism was very simple and
- user1234 (10/46) Mar 24 Thanks.
- H. S. Teoh (38/62) Mar 24 [...]
- user1234 (4/15) Mar 24 Sorry, I see it now. It's the old "furnisher" problem. There was
- Walter Bright (14/15) Mar 24 If I understand this correctly, D has solved this problem:
- Timon Gehr (41/59) Mar 26 Then so has Rust:
- Walter Bright (2/2) Mar 27 It does look like the same idea in the example you gave.
- Timon Gehr (17/32) Mar 24 Not really, the problem is not fixed:
- H. S. Teoh (7/26) Mar 24 And the solution will add yet more complication to an already complex
- user1234 (2/26) Mar 24 git revert is so simple
- H. S. Teoh (9/20) Mar 24 [...]
- Walter Bright (1/1) Mar 24 A shout out to Martin Nowak who implemented the 2 phase lookup.
It's true that writing code in C doesn't automatically make it faster. For example, string manipulation. 0-terminated strings (the default in C) are, frankly, an abomination. String processing code is a tangle of strlen, strcpy, strncpy, strcat, all of which require repeated passes over the string looking for the 0. (Even worse, reloading the string into the cache just to find its length makes things even slower.) Worse is the problem that, in order to slice a string, a malloc is needed to copy the slice to. And then carefully manage the lifetime of that slice. The fix is simple - use length-delimited strings. D relies on them to great effect. This can be done in C, but there is no succor from the language, and such a package is not standardized. I've proposed a simple enhancement for C to make them work https://www.digitalmars.com/articles/C-biggest-mistake.html but nobody in the C world has any interest in it (which is baffling, as it is so simple!). Another source of slowdown in C that became apparent over the years is C is a brittle language, rather than a plastic one. The first algorithm selected for a C project gets so welded into it that it cannot be changed without great difficulty. (And we all know that algorithms are the key to speed, not coding details.) Why does this happen with C? It's because one cannot switch back and forth between a reference type and a value type without extensively rewriting every use of it. For example: ```C struct S { int a; } int foo(struct S s) { return s.a; } int bar(struct S *s) { return s->a; } ``` To switch between reference and value, it's necessary to go through all the code swapping . and ->. It's just too tedious and never happens. In D: ```D struct S { int a; } int foo(S s) { return s.a; } int bar(S *s) { return s.a; } ``` Working on D shows that there is no reason for the C and C++ -> operator to even exist, the . operator covers both bases!
Mar 21
On Sunday, 22 March 2026 at 04:47:41 UTC, Walter Bright wrote:Another source of slowdown in C that became apparent over the years is C is a brittle language, rather than a plastic one.Another example where D shines in this regard is UFCS allowing you to turn fields into methods and vice versa: ```D struct S { ubyte* ptr; ubyte* end; size_t length() => end - ptr; } ``` ```D struct S { ubyte* ptr; size_t length; ubyte* end() => ptr + length; } ``` You don't need to change `.end` into `.end()`, `.end` works on both fields and methods.
Mar 22
On Sunday, 22 March 2026 at 11:56:00 UTC, Dennis wrote:You don't need to change `.end` into `.end()`, `.end` works on both fields and methods.Some languages consider this as a downside. Because of clarity for human or llm who is reading the code - which is trying to understand what is it method or field, structure or pointer to the structure..
Mar 22
On Sunday, 22 March 2026 at 12:23:28 UTC, Sergey wrote:On Sunday, 22 March 2026 at 11:56:00 UTC, Dennis wrote:The same can be said for replacing the `->` operator with a `.`. For example: `int a = variable.value;` Is `variable` a pointer or a number in this example? You don't know. Do you care? No, and if you do then you should know what your code is doing in the first place lolYou don't need to change `.end` into `.end()`, `.end` works on both fields and methods.Some languages consider this as a downside. Because of clarity for human or llm who is reading the code - which is trying to understand what is it method or field, structure or pointer to the structure..
Mar 22
On Sunday, 22 March 2026 at 15:05:41 UTC, Kapendev wrote:The same can be said for replacing the `->` operator with a `.`. For example: `int a = variable.value;` Is `variable` a pointer or a number in this example? You don't know. Do you care? No, and if you do then you should know what your code is doing in the first place lolThis is wrong example Kap. Imagine you have a function.. with many rows. And then you a calling another function there like: ```d // ... many rows above another_func(foo.bar, foo.baz, x); // ... many rows below ``` here for x parameter you need to give a reference to foo. But you don't know which type foo now - is it a pointer or not.. You will have to go somewhere above search the foo somewhere - then go back to another_func and change the x..
Mar 22
On Sunday, 22 March 2026 at 16:32:25 UTC, Sergey wrote:here for x parameter you need to give a reference to foo. But you don't know which type foo now - is it a pointer or not.. You will have to go somewhere above search the foo somewhere - then go back to another_func and change the x..Of course partially tooling is solving this - with properly configured editor - you could see it easier But there are other more complicated examples (with templates involved) where tooling won't help you
Mar 22
On Sunday, 22 March 2026 at 16:32:25 UTC, Sergey wrote:This is wrong example Kap. Imagine you have a function.. with many rows. And then you a calling another function there like: ```d // ... many rows above another_func(foo.bar, foo.baz, x); // ... many rows below ``` here for x parameter you need to give a reference to foo. But you don't know which type foo now - is it a pointer or not.. You will have to go somewhere above search the foo somewhere - then go back to another_func and change the x..You will get a compiler error telling you the type. It's the same thing.
Mar 22
On Sunday, 22 March 2026 at 12:23:28 UTC, Sergey wrote:On Sunday, 22 March 2026 at 11:56:00 UTC, Dennis wrote:and it’s considered a win for each. Neither human nor AI should care if it’s a property or a field. The whole point of properties is being largely equivalent to fields when used. The rather annoying thing about D is that properties aren’t really first-class, but piggy-backed on functions.You don't need to change `.end` into `.end()`, `.end` works on both fields and methods.Some languages consider this as a downside. Because of clarity for human or llm who is reading the code - which is trying to understand what is it method or field, structure or pointer to the structure..
Mar 25
On Wednesday, 25 March 2026 at 13:20:16 UTC, Quirin Schroll wrote:and it’s considered a win for each. Neither human nor AI should care if it’s a property or a field. The whole point of properties is being largely equivalent to fields when used. The rather annoying thing about D is that properties aren’t really first-class, but piggy-backed on functions.For example languages like Rust, Go, and C++ deliberately avoid property syntax because: - It hides computation behind field access - Makes performance less obvious - Reduces clarity (is it a field or a function?)
Mar 25
On Wednesday, 25 March 2026 at 13:20:16 UTC, Quirin Schroll wrote:and it’s considered a win for each. Neither human nor AI should care if it’s a property or a field. The whole point of properties is being largely equivalent to fields when used. The rather annoying thing about D is that properties aren’t really first-class, but piggy-backed on functions.Also Zig mentioned it explicitly: https://ziglang.org/learn/why_zig_rust_d_cpp/ So nothing odd
Mar 25
On Sunday, 22 March 2026 at 11:56:00 UTC, Dennis wrote:On Sunday, 22 March 2026 at 04:47:41 UTC, Walter Bright wrote:That isn’t UFCS, that’s just empty parentheses being optional. Those are completely orthogonal language concepts.Another source of slowdown in C that became apparent over the years is C is a brittle language, rather than a plastic one.Another example where D shines in this regard is UFCS allowing you to turn fields into methods and vice versa: ```D struct S { ubyte* ptr; ubyte* end; size_t length() => end - ptr; } ``` ```D struct S { ubyte* ptr; size_t length; ubyte* end() => ptr + length; } ``` You don't need to change `.end` into `.end()`, `.end` works on both fields and methods.
Mar 25
On Sunday, 22 March 2026 at 04:47:41 UTC, Walter Bright wrote:
It's because one cannot switch back and forth between a
reference type and a value type without extensively rewriting
every use of it. For example:
```C
struct S { int a; }
int foo(struct S s) { return s.a; }
int bar(struct S *s) { return s->a; }
```
To switch between reference and value, it's necessary to go
through all the code swapping . and ->.
Not really, if one has a little for-thought, and commits to
accessing the members via ->, the two become interchangeable,
with no performance impact.
```c
int inner1 (struct foo fa) {
struct foo *fp = &fa;
fp->a += 1;
return fp->a + 1;
}
```
One can also adapt in the other direction if one started with
pointer arguments (add const as desired):
```c
int inner3 (struct foo *fp) {
struct foo fa = *fp;
fa.a += 1;
return fa.a + 1;
}
```
DF
Mar 22
On Sunday, 22 March 2026 at 17:08:05 UTC, Derek Fawcus wrote:On Sunday, 22 March 2026 at 04:47:41 UTC, Walter Bright wrote:One can even play macro games (using _Generic) to make a wrapper for the function, such that one does not even need to go through and update the call sites to add or remove the & . However going back to the original point, as of late last year / early this year it is now obsolete. That specific example of switching the code to use . or -> is something which the LLM assisted coding agents are particularly adept at. Such refactoring tasks are what I've been using it for, where it is quite easy to specify some form of grep pattern and then rules to update the code. So these days that'll take less than an hour to achieve. DFTo switch between reference and value, it's necessary to go through all the code swapping . and ->.Not really, if one has a little for-thought, and commits to accessing the members via ->, the two become interchangeable, with no performance impact.
Mar 22
On Sunday, 22 March 2026 at 17:19:26 UTC, Derek Fawcus wrote:However going back to the original point, as of late last year / early this year it is now obsolete. That specific example of switching the code to use . or -> is something which the LLM assisted coding agents are particularly adept at. Such refactoring tasks are what I've been using it for, where it is quite easy to specify some form of grep pattern and then rules to update the code. So these days that'll take less than an hour to achieve.If that's the standard (unlimited time and resources) then it was never really a thing. You could have always hired someone to make the changes for you. There's really no reason to use high-level programming languages at all if you're willing to make those assumptions.
Mar 22
On 3/22/2026 10:19 AM, Derek Fawcus wrote:One can even play macro games (using _Generic) to make a wrapper for the function, such that one does not even need to go through and update the call sites to add or remove the & .If _Generic is needed, you have outgrown C. (I am regularly baffled by the weird useless things added to C, but the *needed* things are totally ignored.)However going back to the original point, as of late last year / early this year it is now obsolete. That specific example of switching the code to use . or -> is something which the LLM assisted coding agents are particularly adept at.D doesn't need a coding agent to refactor the code. It paid off handsomely with the Warp program I did a few years ago. I found it very easy to try different algorithms and data structures.Such refactoring tasks are what I've been using it for, where it is quite easy to specify some form of grep pattern and then rules to update the code. So these days that'll take less than an hour to achieve.I've done these sorts of refactorings. It takes 0 minutes, because the compiler figures it out and does it. It also doesn't wind up with a blizzard of diffs in the git history. It doesn't need code reviewing, either. As I've become more experienced, my tolerance for all the weird kludges necessary for professional C getting lower and lower. LLMs don't really solve the problem, as the wrangled C code is just as ugly looking. I've used LLMs to a modest extent, and am impressed by it. So, I might be wrong about the above. But it's fun to talk about it!
Mar 22
On 23/03/2026 2:51 PM, Walter Bright wrote:As I've become more experienced, my tolerance for all the weird kludges necessary for professional C getting lower and lower. LLMs don't really solve the problem, as the wrangled C code is just as ugly looking.Its not like we can talk, we've got some real uglies hiding out in our implementation. Like monitor proxy support. Uck, I'd love to gut that out of druntime and swap to an operator overload. But alas not approved, but hopefully that will change.
Mar 22
On Monday, 23 March 2026 at 01:51:40 UTC, Walter Bright wrote:As I've become more experienced, my tolerance for all the weird kludges necessary for professional C getting lower and lower. LLMs don't really solve the problem, as the wrangled C code is just as ugly looking.I recently watched a YouTube video about how LLMs produce almost correct code. It's just good enough that errors slip past the code reviewers, and then down the road you're dealing with those errors as they get caught in production. It hit home, because it matches my experience. The trustworthy solution to the problem under discussion here is to have the LLM write a parser and transpile the old code to its new form. Using D and not having to decide on the trustworthy path is obviously a win.
Mar 22
On Monday, 23 March 2026 at 01:51:40 UTC, Walter Bright wrote:On 3/22/2026 10:19 AM, Derek Fawcus wrote: LLMs don't really solve the problem, as the wrangled C code is just as ugly looking.In the example I cited, that was not an issue. I was able to tightly specify the replacement, such that it effectively added as an editor "search and replace" facility on steroids. So the result was exactly what I would have written. I'm still in the process of evaluating LLM based agents in my workflow, but the above is one where I have concluded they are useful. The one detrimental issue being the volume of change which may result from a global application to fix a poor pattern. However, for your quoted example, that would not arise. As there would only be the one (or small set of) function(s) implementing the algorithm to be changed, together with use of _Generic hidden by a macro to catch all of the call sites. Only if that algorithmic change the proved to be valuable would it then be worth the cost of updating the call instances, and eliminating the _Generic using macro. Then there the review cost for the LLM generated diffs would be minimal. As to using an LLM agent to produce 'original' code for a project, I'm still skeptical.
Mar 23
On Sunday, 22 March 2026 at 04:47:41 UTC, Walter Bright wrote:[...] Working on D shows that there is no reason for the C and C++ -> operator to even exist, the . operator covers both bases!Yes from the user POV. From the compilers-details POV I think that semantics checks for that are awfully complex. Add to this your system of UFCS. Boom, 1000 lines of code to desintricate what the programmer really meant. However that's certain that once implemented properly it's 100% profit for hundreds of programmers.
Mar 23
On 3/23/2026 8:12 AM, user1234 wrote:On Sunday, 22 March 2026 at 04:47:41 UTC, Walter Bright wrote:I admit the implementation code is not a dreamboat. But in defense, in the 1980s I attempted to develop the be-all and end-all windowing user interface library. I soon discovered that what is intuitive and easy for the user is a giant mess of special cases in the implementation. And when the implementation was simple and consistent, the users thought it completely unintuitive. Longtime D users might remember when I was the lone holdout on how the name lookup worked in D. I thought it was perfectly straightforward, and it was easy to implement in clean code. Nobody agreed with me. So now we have a complicated 2-phase lookup that everybody likes. Go figure! P.S. C and C++ require semantic analysis in order to parse the source code correctly (the C cast expressions, and the >> tokens in C++). These are unnecessary and simply bad language design.[...] Working on D shows that there is no reason for the C and C++ -> operator to even exist, the . operator covers both bases!Yes from the user POV. From the compilers-details POV I think that semantics checks for that are awfully complex. Add to this your system of UFCS. Boom, 1000 lines of code to desintricate what the programmer really meant. However that's certain that once implemented properly it's 100% profit for hundreds of programmers.
Mar 23
On 24/03/2026 12:48 PM, Walter Bright wrote:But in defense, in the 1980s I attempted to develop the be-all and end- all windowing user interface library.Did you ever study IBM CUA?
Mar 23
On 3/23/2026 4:49 PM, Richard (Rikki) Andrew Cattermole wrote:Did you ever study IBM CUA?I had the book but never read it. It came out years after my attempt.
Mar 23
On 24/03/2026 3:55 PM, Walter Bright wrote:On 3/23/2026 4:49 PM, Richard (Rikki) Andrew Cattermole wrote:I've got it as well, the last of the series I think it is. https://www.amazon.com/Object-Oriented-Interface-Design-Common-Guidelines/dp/1565291700 You should open it up, it talks about how it combines earlier CUA specifications ;) It originally was about TUI's, not even graphical.Did you ever study IBM CUA?I had the book but never read it. It came out years after my attempt.
Mar 23
On 3/23/2026 8:01 PM, Richard (Rikki) Andrew Cattermole wrote:On 24/03/2026 3:55 PM, Walter Bright wrote:I sold the book (!) because I wanted to focus on other things and the book fetched a good price.On 3/23/2026 4:49 PM, Richard (Rikki) Andrew Cattermole wrote:I've got it as well, the last of the series I think it is. https://www.amazon.com/Object-Oriented-Interface-Design-Common-Guidelines/dp/1565291700 You should open it up, it talks about how it combines earlier CUA specifications ;) It originally was about TUI's, not even graphical.Did you ever study IBM CUA?I had the book but never read it. It came out years after my attempt.
Mar 24
On 24/03/2026 8:05 PM, Walter Bright wrote:On 3/23/2026 8:01 PM, Richard (Rikki) Andrew Cattermole wrote:Oh lol, its cheap now and also on archive.org.On 24/03/2026 3:55 PM, Walter Bright wrote:I sold the book (!) because I wanted to focus on other things and the book fetched a good price.On 3/23/2026 4:49 PM, Richard (Rikki) Andrew Cattermole wrote:I've got it as well, the last of the series I think it is. https://www.amazon.com/Object-Oriented-Interface-Design-Common- Guidelines/dp/1565291700 You should open it up, it talks about how it combines earlier CUA specifications ;) It originally was about TUI's, not even graphical.Did you ever study IBM CUA?I had the book but never read it. It came out years after my attempt.
Mar 24
On Monday, 23 March 2026 at 23:48:27 UTC, Walter Bright wrote:So now we have a complicated 2-phase lookup that everybody likes.Again, not everybody likes it.
Mar 24
On Tuesday, 24 March 2026 at 10:36:19 UTC, Max Samukha wrote:On Monday, 23 March 2026 at 23:48:27 UTC, Walter Bright wrote:I don't know what this "2-phases lookup system" is refering to (my interest in D started by 2014 let's say and I have the feeling that this is an older topic). What was the problem in first place ?So now we have a complicated 2-phase lookup that everybody likes.Again, not everybody likes it.
Mar 24
On Tue, Mar 24, 2026 at 12:38:28PM +0000, user1234 via Digitalmars-d wrote:On Tuesday, 24 March 2026 at 10:36:19 UTC, Max Samukha wrote:In the beginning, D's symbol lookup mechanism was very simple and straightforward: whenever an import statement is encountered, symbols from an imported module are loaded and injected into the symbol table at the current scope. This is straightforward to implement (you literally translate "import xyz" as parsing xyz and adding its public symbols to the current scope's symbol table). However, that led to counterintuitive behaviours like: void main() { myFunc("abc"); } void myFunc(string text) { writeln(text); // prints "abc" import std.conv; writeln(text); // prints "" } Walter was very resistant to changing this behaviour, as all proposed solutions involved "inelegant" complications in the semantics and implementation of "import". Eventually, however, the crowd prevailed and Walter relented. T -- Why does a pound of hamburger have less energy than a pound of steak? Because it is in the ground state.On Monday, 23 March 2026 at 23:48:27 UTC, Walter Bright wrote:I don't know what this "2-phases lookup system" is refering to (my interest in D started by 2014 let's say and I have the feeling that this is an older topic). What was the problem in first place ?So now we have a complicated 2-phase lookup that everybody likes.Again, not everybody likes it.
Mar 24
On Tuesday, 24 March 2026 at 14:36:57 UTC, H. S. Teoh wrote:On Tue, Mar 24, 2026 at 12:38:28PM +0000, user1234 via Digitalmars-d wrote:Thanks. I would not like to be rude and reopen old wounds but this looks more a problem of `text` being either a variable or a function and as D allows function calls without params to me it looks like it has never been a problem of lookup. Now imagine std.conv.text is a global variable. That does not change anything. Order of declaration matters in the local scope. Anyway, despite of this curious change, the front-end is still fast.On Tuesday, 24 March 2026 at 10:36:19 UTC, Max Samukha wrote:In the beginning, D's symbol lookup mechanism was very simple and straightforward: whenever an import statement is encountered, symbols from an imported module are loaded and injected into the symbol table at the current scope. This is straightforward to implement (you literally translate "import xyz" as parsing xyz and adding its public symbols to the current scope's symbol table). However, that led to counterintuitive behaviours like: void main() { myFunc("abc"); } void myFunc(string text) { writeln(text); // prints "abc" import std.conv; writeln(text); // prints "" } Walter was very resistant to changing this behaviour, as all proposed solutions involved "inelegant" complications in the semantics and implementation of "import". Eventually, however, the crowd prevailed and Walter relented. TOn Monday, 23 March 2026 at 23:48:27 UTC, Walter Bright wrote:I don't know what this "2-phases lookup system" is refering to (my interest in D started by 2014 let's say and I have the feeling that this is an older topic). What was the problem in first place ?So now we have a complicated 2-phase lookup that everybody likes.Again, not everybody likes it.
Mar 24
On Tue, Mar 24, 2026 at 03:25:29PM +0000, user1234 via Digitalmars-d wrote:On Tuesday, 24 March 2026 at 14:36:57 UTC, H. S. Teoh wrote:[...][...]In the beginning, D's symbol lookup mechanism was very simple and straightforward: whenever an import statement is encountered, symbols from an imported module are loaded and injected into the symbol table at the current scope. This is straightforward to implement (you literally translate "import xyz" as parsing xyz and adding its public symbols to the current scope's symbol table). However, that led to counterintuitive behaviours like: void main() { myFunc("abc"); } void myFunc(string text) { writeln(text); // prints "abc" import std.conv; writeln(text); // prints "" }I would not like to be rude and reopen old wounds but this looks more a problem of `text` being either a variable or a function and as D allows function calls without params to me it looks like it has never been a problem of lookup. Now imagine std.conv.text is a global variable. That does not change anything. Order of declaration matters in the local scope.It's not about `text` being a function called without parens; it's about an imported module hijacking symbols in the local scope. The same problem occurs in this situation: ``` // xyz.d module xyz; static immutable text = "haha you got hijacked"; // main.d module main; void main() { myFunc("abc"); } void myFunc(string text) { writeln(text); // prints "abc" import xyz; // N.B.: we never imported `text` explicitly writeln(text); // prints "haha you got hijacked" } ``` This is a problem because perhaps module xyz didn't declare `text` when this code was written. Then later on, upstream rewrote the implementation and added a declaration of `text`. Suddenly, unrelated code in myFunc() has broken because its semantics silently changed from under its carpet: the newly-added declaration of `text` in xyz has hijacked the function parameter `text` in an unrelated module that just happened to import it. This is only one instance of the problem. Another instance concerns *private* symbols in the imported module causing a conflict with a local symbol in the importing module. (Remember, this is a logical consequence of the simple and elegant concept that `import` simply injects symbols into the local scope -- the injected symbols include private symbols. Treating private symbols specially was one of the "inelegant" things that complicated the implementation of imports, among other things.) T -- My stomach is flat. The L is just silent!
Mar 24
On Tuesday, 24 March 2026 at 15:41:59 UTC, H. S. Teoh wrote:On Tue, Mar 24, 2026 at 03:25:29PM +0000, user1234 via Digitalmars-d wrote:Sorry, I see it now. It's the old "furnisher" problem. There was something about that a few days ago on Y news https://www.boxyuwu.blog/posts/an-incoherent-rust/[...][...][...][...][...]It's not about `text` being a function called without parens; it's about an imported module hijacking symbols in the local scope. The same problem occurs in this situation: [...]
Mar 24
On 3/24/2026 12:23 PM, user1234 wrote:https://www.boxyuwu.blog/posts/an-incoherent-rust/If I understand this correctly, D has solved this problem: ```d import a; // exports 'x' import b; // exports 'x' int z = x; // error, multiple definition of 'x' ``` The resolution: ```d import a; // exports 'x' import b; // exports 'x' alias x = b.x; int z = x; // b.x is selected ```
Mar 24
On 3/25/26 03:32, Walter Bright wrote:On 3/24/2026 12:23 PM, user1234 wrote:Then so has Rust: ```rust mod a { pub const x : i32 = 2; } mod b { pub const x : i32 = 3; } use a::*; use b::*; const z : i32 = x; // error: `x` is ambiguous fn main(){ print!("{}", z); } ``` The resolution: ```rust mod a { pub const x : i32 = 2; } mod b { pub const x : i32 = 3; } use a::*; use b::*; use b::x as x; const z : i32 = x; // b::x is selected fn main(){ print!("{}", z); } // 3 ``` The issue is a bit more fundamental to their traits design than just disambiguating names. They don't even have names for implementations of traits. Once you have names, in order to detect mismatches between associated types, you need some sort of dependent typing, for example path-dependent types. This is because implementations are values, and the associated types depend on these values. Enforcing that there can be only one implementation of a trait for a given type gets around this dependency: you can treat the mapping from implementation to associated type as just a mapping from the type to the associated type given by the unique implementation.https://www.boxyuwu.blog/posts/an-incoherent-rust/If I understand this correctly, D has solved this problem: ```d import a; // exports 'x' import b; // exports 'x' int z = x; // error, multiple definition of 'x' ``` The resolution: ```d import a; // exports 'x' import b; // exports 'x' alias x = b.x; int z = x; // b.x is selected ```
Mar 26
It does look like the same idea in the example you gave. D has a lot less typing!
Mar 27
On 3/24/26 15:36, H. S. Teoh wrote:
However, that led to counterintuitive behaviours like:
void main() {
myFunc("abc");
}
void myFunc(string text) {
writeln(text); // prints "abc"
import std.conv;
writeln(text); // prints ""
}
Walter was very resistant to changing this behaviour, as all proposed
solutions involved "inelegant" complications in the semantics and
implementation of "import". Eventually, however, the crowd prevailed
and Walter relented.
Not really, the problem is not fixed:
```d
import std.stdio;
string readAndLog(string filename){
import std.file;
auto text=readText(filename);
write(filename," read successfully!\n");
return text;
}
void main(){
writeln(readAndLog("important_data.txt"));
}
```
https://github.com/dlang/dmd/issues/19272
So what we have now is a compromise: It's both broken and not entirely
straightforward.
Mar 24
On Tue, Mar 24, 2026 at 08:50:26PM +0100, Timon Gehr via Digitalmars-d wrote:
[...]
```d
import std.stdio;
string readAndLog(string filename){
import std.file;
auto text=readText(filename);
write(filename," read successfully!\n");
return text;
}
void main(){
writeln(readAndLog("important_data.txt"));
}
```
https://github.com/dlang/dmd/issues/19272
So what we have now is a compromise: It's both broken and not entirely
straightforward.
And the solution will add yet more complication to an already complex
import symbol resolution system. :-D
T
--
What do you get if you throw a grenade into a French kitchen? Linoleum blown
apart.
Mar 24
On Tuesday, 24 March 2026 at 20:17:16 UTC, H. S. Teoh wrote:On Tue, Mar 24, 2026 at 08:50:26PM +0100, Timon Gehr via Digitalmars-d wrote: [...]git revert is so simple```d import std.stdio; string readAndLog(string filename){ import std.file; auto text=readText(filename); write(filename," read successfully!\n"); return text; } void main(){ writeln(readAndLog("important_data.txt")); } ``` https://github.com/dlang/dmd/issues/19272 So what we have now is a compromise: It's both broken and not entirely straightforward.And the solution will add yet more complication to an already complex import symbol resolution system. :-D T
Mar 24
On Tue, Mar 24, 2026 at 11:31:25PM +0000, user1234 via Digitalmars-d wrote:On Tuesday, 24 March 2026 at 20:17:16 UTC, H. S. Teoh wrote:[...]On Tue, Mar 24, 2026 at 08:50:26PM +0100, Timon Gehr via Digitalmars-d wrote: [...][...]https://github.com/dlang/dmd/issues/19272 So what we have now is a compromise: It's both broken and not entirely straightforward.And the solution will add yet more complication to an already complex import symbol resolution system. :-Dgit revert is so simpleYes, and it will equally simply break a ton of user code that has come to rely on the new behaviour, thus causing outrage among users at the next release. :-P T -- In theory, there is no difference between theory and practice.
Mar 24
A shout out to Martin Nowak who implemented the 2 phase lookup.
Mar 24









Sergey <kornburn yandex.ru> 