Jump to page: 1 24  
Page
Thread overview
[DIP] In-place struct initialization
Jul 30, 2016
cym13
Jul 30, 2016
Cauterite
Jul 30, 2016
cym13
Jul 30, 2016
Cauterite
Jul 30, 2016
cym13
Jul 31, 2016
deadalnix
Jul 31, 2016
cym13
Jul 31, 2016
deadalnix
Jul 31, 2016
Enamex
Jul 31, 2016
Lodovico Giaretta
Jul 31, 2016
Patrick Schluter
Aug 03, 2016
deadalnix
Aug 03, 2016
Enamex
Aug 03, 2016
deadalnix
Aug 03, 2016
ZombineDev
Aug 04, 2016
Patrick Schluter
Aug 04, 2016
ZombineDev
Aug 04, 2016
ketmar
Aug 05, 2016
ZombineDev
Aug 05, 2016
ketmar
Aug 05, 2016
deadalnix
Aug 05, 2016
ketmar
Aug 08, 2016
Cauterite
Aug 08, 2016
ketmar
Aug 05, 2016
Chris Wright
Aug 04, 2016
Chris Wright
Aug 04, 2016
ketmar
Aug 11, 2016
Georgi D
Aug 02, 2016
Jacob Carlborg
Aug 02, 2016
Jacob Carlborg
July 30, 2016
In accordance to the new DIP process you can find the full presentation of the change here: https://github.com/dlang/DIPs/pull/22

This DIP aims at providing better orthogonality and more importantly a way to have keyword arguments in the language at little cost and great benefit by extending static initialization to avoid having to declare a variable. It makes the following code legal:

    struct totalArgs {
        int tax;
        int discount;
    }

    int total(int subtotal, totalArgs args = totalArgs.init) {
        return subtotal + args.tax - args.discount;
    }

    unittest {
        assert(total(42) == 42);
        assert(total(42, totalArgs(tax: 50)) == 92);
        assert(total(42, totalArgs(discount: 20, tax: 50)) == 72);

        int defaultTotal(int subtotal) {
            immutable defaultSet = totalArgs(tax: 20);
            return total(subtotal, defaultSet);
        }
    }

Here is the rational as found in the DIP:

Static struct initialization has great properties:

- It is explicit using named attributes
- Order of declaration doesn't matter
- Not all attributes have to be specified

No function call provide those properties, and consequently no constructor
can benefit from it either. Authorizing such struct initialization makes the
language more orthogonal and opens new doors.

The most interesting is to use structs to mimic keyword arguments for
functions. By encapsulating possible arguments in a struct it is possible to
use in-place initialization to provide a clean interface very similar to
keyword arguments such as seen in python or ruby.

As it stands now the way to provide complex argument set to a function is
either to generate lots of constructors for the different cases which is
messy or by setting a struct up before passing it to the function in a C-way
fashion. This change provides ways to design better high-level interfaces.

Besides the change is completely retro-compatible in a nice way: the library
itself is just defining an argument struct and using it in its function
interface. Code using older compilers can setup the struct without in-place
initialization and modern compilers benefit from a cleaner interface.

This change also helps interfacing C code that uses structs.


I'm convinced such a change would be great for D but only if properly reviewed, please don't hesitate to comment it.
July 30, 2016
On Saturday, 30 July 2016 at 21:42:42 UTC, cym13 wrote:
> ...

Here's something you might enjoy in the meantime:
https://github.com/Cauterite/dlang-pod-literals/blob/master/podliterals.d


July 30, 2016
On Saturday, 30 July 2016 at 21:45:31 UTC, Cauterite wrote:
> On Saturday, 30 July 2016 at 21:42:42 UTC, cym13 wrote:
>> ...
>
> Here's something you might enjoy in the meantime:
> https://github.com/Cauterite/dlang-pod-literals/blob/master/podliterals.d

Thanks, I'm aware of this work but some points just aren't good enough IMHO. We can do better than that. First of all the syntax is too far appart from traditional field assignment which is always done using ':' . I understand why it is so but still it makes one more thing to remember. Calling lambdas all the time isn't free while the change I propose is static. Those lambdas aren't optimized away by DMD and while that might change I just don't feel like trusting it. And more importantly it doesn't work with common structs, you have to pass it to your template first and then it isn't the struct anymore. There are just too many ways for this to get wrong in my opinion.

Note that I find the idea ingenious and interesting, I just think we can do better than that.
July 30, 2016
On Saturday, 30 July 2016 at 22:05:29 UTC, cym13 wrote:
> On Saturday, 30 July 2016 at 21:45:31 UTC, Cauterite wrote:
>> On Saturday, 30 July 2016 at 21:42:42 UTC, cym13 wrote:
>>> ...
>>
>> Here's something you might enjoy in the meantime:
>> https://github.com/Cauterite/dlang-pod-literals/blob/master/podliterals.d
>
> Thanks, I'm aware of this work but some points just aren't good enough IMHO. We can do better than that. First of all the syntax is too far appart from traditional field assignment which is always done using ':' . I understand why it is so but still it makes one more thing to remember. Calling lambdas all the time isn't free while the change I propose is static. Those lambdas aren't optimized away by DMD and while that might change I just don't feel like trusting it. And more importantly it doesn't work with common structs, you have to pass it to your template first and then it isn't the struct anymore. There are just too many ways for this to get wrong in my opinion.
>
> Note that I find the idea ingenious and interesting, I just think we can do better than that.

It does work with common structs:

	struct Xyzº {
		int X;
		wstring Y;
		Object Z;
	};
	auto Thing = pod!(Xyzº,
		Y => `asdf`w,
		X => 3,
		Z => null,
	);

	assert(is(typeof(Thing) == Xyzº));

But anyway, you don't need to convince me that having a native language feature would be superior to this template nonsense :P
It's just a workaround for the moment (albeit a bloody powerful workaround!)

Although I do like being able to both define and instanciate a structure in the same expression (especially with unions). Maybe that could be a future extension to your DIP.
July 30, 2016
On Saturday, 30 July 2016 at 22:20:49 UTC, Cauterite wrote:
> On Saturday, 30 July 2016 at 22:05:29 UTC, cym13 wrote:
>> [...]
>
> It does work with common structs:

Sorry, I hadn't noticed.

> But anyway, you don't need to convince me that having a native language feature would be superior to this template nonsense :P
> It's just a workaround for the moment (albeit a bloody powerful workaround!)
>
> Although I do like being able to both define and instanciate a structure in the same expression (especially with unions). Maybe that could be a future extension to your DIP.

I think it should be a different DIP, while I find the idea interesting it doesn't share the same purpose as far as I can tell.
July 31, 2016
On Saturday, 30 July 2016 at 21:42:42 UTC, cym13 wrote:
> The most interesting is to use structs to mimic keyword arguments for
> functions. By encapsulating possible arguments in a struct it is possible to
> use in-place initialization to provide a clean interface very similar to
> keyword arguments such as seen in python or ruby.
>

That doesn't help. In fact, it makes things worse as now constructor calls and function call do not have the same syntax. You've just created an holly mess in the parser.

If something we should strive to get constructor call more like regular function call rather than less (for instance by behaving the same way when it comes to IFTI).

It is also unclear how overload resolution is supposed to work.

If I may suggest one thing it is to not start with the intended result for the DIP, but start from the intended change int he language, then, and only then, examine what comes out of it.

July 31, 2016
On Sunday, 31 July 2016 at 04:55:31 UTC, deadalnix wrote:
> On Saturday, 30 July 2016 at 21:42:42 UTC, cym13 wrote:
>> The most interesting is to use structs to mimic keyword arguments for
>> functions. By encapsulating possible arguments in a struct it is possible to
>> use in-place initialization to provide a clean interface very similar to
>> keyword arguments such as seen in python or ruby.
>>
>
> That doesn't help. In fact, it makes things worse as now constructor calls and function call do not have the same syntax. You've just created an holly mess in the parser.
>
> If something we should strive to get constructor call more like regular function call rather than less (for instance by behaving the same way when it comes to IFTI).
>
> It is also unclear how overload resolution is supposed to work.
>
> If I may suggest one thing it is to not start with the intended result for the DIP, but start from the intended change int he language, then, and only then, examine what comes out of it.

I don't understand this comment. This isn't about construction, it's about initialization, the call can occur only at one precise time and no there is no overload concern as there is no function call. The proposed change is litteraly just equivalent to the already existing struct initialization, just made usable:

    struct S {
        int a;
        int b;
    }

    auto s = S(b:42);
    // equivalent to
    S s = { b:42 };

Having the possibility to initialize structs without tying them to a variable
proves useful when combined with functions that take this struct but those
functions aren't directly impacted by the change.

July 31, 2016
On Sunday, 31 July 2016 at 07:10:46 UTC, cym13 wrote:
> I don't understand this comment.

That's because you haven't tried to specify the grammar. I suggest you try.

July 31, 2016
On Sunday, 31 July 2016 at 07:10:46 UTC, cym13 wrote:
> The proposed change is litteraly just equivalent to the already existing struct initialization, just made usable:
>
>     struct S {
>         int a;
>         int b;
>     }
>
>     auto s = S(b:42);
>     // equivalent to
>     S s = { b:42 };
>
> Having the possibility to initialize structs without tying them to a variable
> proves useful when combined with functions that take this struct but those
> functions aren't directly impacted by the change.

I suggest extending the existing `S s = {field: value}` syntax to allow specifying the type itself next to the field list and make it usable generally everywhere.

So, instead:

takeThing(Thing{ field: val, num: 43 });

It shouldn't clash with anything else, I think.
July 31, 2016
On Sunday, 31 July 2016 at 13:39:58 UTC, Enamex wrote:
> I suggest extending the existing `S s = {field: value}` syntax to allow specifying the type itself next to the field list and make it usable generally everywhere.
>
> So, instead:
>
> takeThing(Thing{ field: val, num: 43 });
>
> It shouldn't clash with anything else, I think.

I support this idea of extending curly-brace initializers. It would be very useful and less ambiguous than parenthesized initializers.

[A thread about this]
http://forum.dlang.org/post/ni0u47$2100$1@digitalmars.com

[An issue about this]
https://issues.dlang.org/show_bug.cgi?id=15692
« First   ‹ Prev
1 2 3 4