6 days ago
On Friday, 12 September 2025 at 23:58:57 UTC, Brother Bill wrote:
> On Friday, 12 September 2025 at 21:46:51 UTC, monkyyy wrote:
>> On Friday, 12 September 2025 at 20:10:25 UTC, H. S. Teoh wrote:
>>> Phobos code was legendary for being a standard library that didn't make your head hurt when you read it. (If you've ever tried reading the source code for Glibc, or the standard library for almost any other language, really, you'll know what I mean.)  It was exemplary of how D code ought to be written.  It probably still is today to some extent, though sadly over the years it has fallen into the mud and come out hairy on multiple occasions, so it ain't as pretty as it used to be anymore.)
>>
>>> It probably still is today to some extent
>>
>> *loud silence*
>>
>> Its probably time to raise some standards
>
> Is it time to consider D 3.x.x, that takes the best of D, discards the mistakes, the mud and the hair, so most well written D 2.x.x programs still work?

Your welcome in to come to opend

>
> Should it learn lessons from Rust

God no

> Should D follow Gleam, an Erlang variant in having functional programming with pattern matching, deconstruction, etc?

Templates are fundamentally compile time, memoized, pattern matching

Full pattern matching no, I want partial `value` pattern matching tho

> And take from Zig multiple ways to allocate memory?

That would be one of the allocation extremist factions I mentioned and honestly the one that has walters ear most.
5 days ago
On Friday, September 12, 2025 5:58:57 PM Mountain Daylight Time Brother Bill via Digitalmars-d-learn wrote:
> Is it time to consider D 3.x.x, that takes the best of D, discards the mistakes, the mud and the hair, so most well written D 2.x.x programs still work?

Unless, something significant changes, there will be no D3. As it is, the change from D1 to D2 almost destroyed D (even if the language is arguably much better off with the changes), and Walter is adamant that we're not doing that again. Editions are being added to the language to make it so that a module can be marked as using a specific Edition of the language in order to try to make it easier to make breaking changes, which will potentially mean that larger changes will come to D than we've done in a while (e.g. making @safe the default), but we're not going to make changes drastic enough that they would require D3.

And really, even if we decided to do a D3, there would be so much disagreement over what the best changes would be that that alone would likely shatter the community.

- Jonathan M Davis




5 days ago
On Friday, September 12, 2025 9:20:38 AM Mountain Daylight Time Brother Bill via Digitalmars-d-learn wrote:
> Is is possible to 'disable' .init for a struct?

Technically, yes, but you should absolutely never do it, and it will likely become illegal to do so at some point in the future.

init is a core part of the language, and all types have it. The fact that the ability to disable default initialization was added was arguably a mistake. There _are_ cases where it can be quite useful, so whether it should be allowed is definitely debatable, but the fact that it's a thing has definitely complicated the language. It's particularly problematic for generic code.

And even when default initialization is disabled, there are still cases where the init value is required (even if you the average programmer should not be writing such code).

For instance, the init value is what's used by the compiler (and in some cases, the runtime) when initializing a variable of that type prior to calling its constructor. Even when a struct has disabled default initialization, that's still the case.

Unfortunately, it _is_ still legal to declare your own init member for a type, but doing that just breaks things, and you should never do it. And because it's possible to declare an init member, it's possible to declare an init member with @disable, but that will ultimately just break code. Don't do it.

At some point, it probably will become illegal to declare a member called init precisely because it breaks things. The only reason that it's legal is that Walter orignally had thought that it would be a good idea to make it possible to define your own init value to override the default behavior, but in practice, things do not work that way, and you should never attempt it if you don't want broken code. D code in general (including in the runtime) assumes that T.init is the init value as defined by the compiler and that it has not been disabled in any fashion. And your code should not attempt to break that assumption.

That being said, normal code should not be using an explicit init value with any type which has disabled default initialization, because it makes it far too easy to accidentally bypass that restriction.

And really, in general, you just shouldn't be using the init value of a type explicitly, and the fact that default initialization can be disabled is a big part of that. A related issue is the fact that non-static nested structs have a context pointer, and while it will be properly initialized when the struct is default-initialized, it will be initialized to null if you explicitly initialize a struct with its init value (because the value for the context pointer in the init value is null).

So, in general, if possible, you should let structs be default-initalized rather than trying to explicitly give them their default value, but in cases where you do need to explicitly pass the default value - e.g. foo(T.init) - it's still better to not use the init value.

One workaround that's sometimes used is to use T() instead of T.init, so you'd do something like foo(T()) instead. This works in _most_ situations and is very much preferable to using T.init, because T() will normally give you the default-initialized value for T (including initializing the context pointer if T is a non-static nested struct), and it won't compile if default initialization has been disabled for T. So, you won't accidentally use the init value as the default-initialized value of a type that doesn't have default initialization.

However, that falls apart when static opCall is involved. If a static opCall which takes no arguments has been declared for T, then that's what T() will use instead of giving the default-initialized value. This means that in normal generic code, you can't use T.init, and you can't use T(). Rather, you need to do something like declare a variable without giving it an explicit value and then use that variable. Phobos v3 will have a helper template for that (and maybe it should be merged into Phobos v2), which is basically

template defaultInit(T)
if (is(typeof({T t;})))
{
    enum defaultInit = (){ T retval; return retval; }();
}

so that you can then use defaultInit!Foo instead of Foo.init or Foo(), but whether such a helper template is used or not, ultimately, most generic code should not be using T() or T.init, because it will not work correctly with all types.

So, in your own code, you shouldn't normally use T.init or T(), and you shouldn't disable default initialization unless it's absolutely necessary, since the type will then not compile with some language features (e.g. dynamic arrays), because they require default initialization to work, and there is likely to be some generic code which used T.init when it shouldn't have, because it didn't used to be possible to disable default initialization (or because the programmer who wrote it forgot to take disable default initialization into account). So, if you're passing a type which has disabled default initialization to third party code, there's a real chance that it'll end up being initialized with its init value at some point anyway, because 99.99+% of types don't have that problem, and unless someone thought to test for it, it probably wasn't tested properly with a particular piece of code.

And trying to disable the init value will make things even worse, because there is legitimately code that needs to use the init value to do its job even if default initialization is disabled for a type. Similarly, if you declare a type which disables default initialization and which has a destructor, the destructor needs to work when the object is its init value, since there are situations where that's going to happen. That doesn't mean that the type needs to have all of its functionality work when it's its init value, since it shouldn't be being set to its init value under normal circumstances, but there are still going to be situtations where it can happen, and the destructor will be run after that (e.g. if an object is moved, the variable that's left behind will be set to the type's init value so that that can be destroyed instead of the object that was moved).

So, all in all, I'd advise against trying to disable default initialization for a struct unless you really know what you're doing. And if you have a type that really can't work properly with default initialization, you might want to consider using a class instead of a struct, since you won't get any class objects separate from a reference, and the init value for the reference is null. So, any class object that you use is going to have been constructed with one of its constructors, and you won't have to worry about default-initialized class objects.

- Jonathan M Davis




1 2
Next ›   Last »