digitalmars.D.learn - Any way to automatically convert structs on return?
- Emma (31/31) Aug 01 This code works:
- Richard (Rikki) Andrew Cattermole (3/3) Aug 01 No, D does not support implicit construction.
- IchorDev (8/39) Aug 01 I’m pretty sure this is intentional to prevent ambiguity, but I
- user1234 (4/7) Aug 01 The problem would be that sorting the candidates of an overload
- IchorDev (4/7) Aug 01 Please elaborate about how this would interact with function
- Nick Treleaven (4/6) Aug 01 Doing `= void` can violate the assumptions of a destructor of T.
- Dukc (7/10) Aug 01 While this isn't exactly less verbose, I mention it because at least you...
- Lance Bachmeier (14/21) Aug 01 For the program you've written, I'm happy it doesn't compile,
- Emma (10/15) Aug 01 Thanks everyone for the replies! I just thought it was weird that
- Juraj (6/12) Aug 02 Not D per se, but you can check Adam D. Ruppe's current work.
This code works: ```d struct None {} struct Option(T) { bool hasSome; T value; this(None) {} this(T v) { hasSome = true; value = v; } } Option!int a = 123; // automatically constructs an Option!int from a bare int Option!int b = None(); // same as above but with None ``` but this doesn't: ```d Option!int something() { return None(); // Error: cannot implicitly convert expression `None()` of type `None` to `Option!int` } ``` This kind of prevents ergonomic code like the above. Instead you have to use a function like `Option!T None(T)() => Option!T()` and then you have to repeat yourself with `return None!int` and etc... it's quite annoying :( In C++ you may do this fairly easily, but of course there are various pitfalls because it's C++. But at least you can opt out with `explicit` most of the time. Thanks in advance!
Aug 01
No, D does not support implicit construction. However in saying that, I will continue to argue in support of sum types when they get added to the language to support implicit construction!
Aug 01
On Thursday, 1 August 2024 at 07:25:53 UTC, Emma wrote:This code works: ```d struct None {} struct Option(T) { bool hasSome; T value; this(None) {} this(T v) { hasSome = true; value = v; } } Option!int a = 123; // automatically constructs an Option!int from a bare int Option!int b = None(); // same as above but with None ``` but this doesn't: ```d Option!int something() { return None(); // Error: cannot implicitly convert expression `None()` of type `None` to `Option!int` } ``` This kind of prevents ergonomic code like the above. Instead you have to use a function like `Option!T None(T)() => Option!T()` and then you have to repeat yourself with `return None!int` and etc... it's quite annoying :( In C++ you may do this fairly easily, but of course there are various pitfalls because it's C++. But at least you can opt out with `explicit` most of the time. Thanks in advance!I’m pretty sure this is intentional to prevent ambiguity, but I can’t quite remember what the point of that is. You can always just write the constructor manually, but yes it’s a hassle. I wonder how open people would be to changing this restriction? P.S. You might want to put `value = void`, otherwise it’ll always be default-constructed. Phobos also has `Nullable` if you want another implementation for reference.
Aug 01
On Thursday, 1 August 2024 at 08:46:00 UTC, IchorDev wrote:[...] I’m pretty sure this is intentional to prevent ambiguity, but I can’t quite remember what the point of that is.The problem would be that sorting the candidates of an overload set would be more complicated. Also in certain cases it would be less obvious to get which one is selected.
Aug 01
On Thursday, 1 August 2024 at 09:55:08 UTC, user1234 wrote:The problem would be that sorting the candidates of an overload set would be more complicated. Also in certain cases it would be less obvious to get which one is selected.Please elaborate about how this would interact with function overloads at all? The function has the same parameters, same return type, same attributes… what’s different exactly?
Aug 01
On Thursday, 1 August 2024 at 10:59:03 UTC, IchorDev wrote:On Thursday, 1 August 2024 at 09:55:08 UTC, user1234 wrote:That was a general criticism of implicit construction. The classic example is ```d struct S {int i;} function f(S s); function f(int i); unittest { f(0); } // both match ``` unless the idea would rather be to allow implicit construction only in the context of initialization.The problem would be that sorting the candidates of an overload set would be more complicated. Also in certain cases it would be less obvious to get which one is selected.Please elaborate about how this would interact with function overloads at all?
Aug 01
On Thursday, 1 August 2024 at 14:20:29 UTC, user1234 wrote:That was a general criticism of implicit construction.We are only talking about it in the context of returning from a function.The classic example is ```d struct S {int i;} function f(S s); function f(int i); unittest { f(0); } // both match ``` unless the idea would rather be to allow implicit construction only in the context of initialization.You are wasting my time. Show me how this applies to retuning from within a function.
Aug 01
On Thursday, 1 August 2024 at 08:46:00 UTC, IchorDev wrote:P.S. You might want to put `value = void`, otherwise it’ll always be default-constructed.Doing `= void` can violate the assumptions of a destructor of T. Nullable uses a union to store T, so it can decide when to call the destructor.
Aug 01
Emma kirjoitti 1.8.2024 klo 10.25:This kind of prevents ergonomic code like the above. Instead you have to use a function like `Option!T None(T)() => Option!T()` and then you have to repeat yourself with `return None!int` and etc... it's quite annoying :(While this isn't exactly less verbose, I mention it because at least you don't have to write the type twice: ```D Option!int something() { return typeof(return)(None()); }
Aug 01
On Thursday, 1 August 2024 at 07:25:53 UTC, Emma wrote:but this doesn't: ```d Option!int something() { return None(); // Error: cannot implicitly convert expression `None()` of type `None` to `Option!int` } ```For the program you've written, I'm happy it doesn't compile, because a lot of the time the compiler would be making buggy code compile - though I would love to have a way to do it explicitly. In this case you can change your definition of None to use alias this and it will compile: ``` struct None { alias convert this; Option!int convert() { return Option!int(None()); } } ```
Aug 01
Thanks everyone for the replies! I just thought it was weird that implicit construction is seemingly supported when directly initialising a struct but not in any other case. I guess it's because it's clearly less ambiguous. On Thursday, 1 August 2024 at 13:07:09 UTC, Lance Bachmeier wrote:For the program you've written, I'm happy it doesn't compile, because a lot of the time the compiler would be making buggy code compile - though I would love to have a way to do it explicitly. In this case you can change your definition of None to use alias this and it will compile:The alias this doesn't work generically, though. Either way I agree that implicit construction, if it was present in D, should not be the default, instead being opt-in like say through an `implicit this(...)` or whatever instead of C++'s horrendous implicit by default behaviour.
Aug 01
On Thursday, 1 August 2024 at 07:25:53 UTC, Emma wrote:```d Option!int something() { return None(); // Error: cannot implicitly convert expression `None()` of type `None` to `Option!int` } ```Not D per se, but you can check Adam D. Ruppe's current work. If I am not mistaken, the thing you are asking for is already possible in the nightly release. https://dpldocs.info/this-week-in-arsd/Blog.Posted_2024_02_20.html#implicit-construction Juraj
Aug 02