Jump to page: 1 2
Thread overview
July 18
Here's a toy version of a problem in the wild.

struct S {
    long first;
    union T {
        long one;
        double two;
    }
    T second;
    alias First = first;
    alias Second = second.one;
}

void main() {
    S x;
    x.First = 4;
    x.Second = 5; // compilation error: "Error: need this for one of type long"
}

Second is a fixed offset into an S and it would be nice to have a name for it. Why doesn't alias know it's OK?

I can work around this with some duplication as follows.

struct S {
    long first;
    union {
        long one;
        double two;
        union T {
            long one;
            double two;
        }
        T second;
    }
    alias First = first;
    alias Second = one;
}

void main() {
    S x;
    x.First = 4;
    x.Second = 5;
    x.second.one = 6;
    import std.stdio;
    writeln(x);
    writeln(x.one);
    writeln(x.Second);
}

Is there any way to avoid the duplication of the entries in the anonymous union, aside from using a mixin template?

Is there some other way (not involving writing a function) to work around this?

July 18
On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant wrote:
> Is there any way to avoid the duplication of the entries in the anonymous union, aside from using a mixin template?

I think this would be fixed if https://github.com/dlang/dmd/pull/11273 gets merged.
July 19
On Saturday, 18 July 2020 at 22:49:18 UTC, Dennis wrote:
> On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant wrote:
>> Is there any way to avoid the duplication of the entries in the anonymous union, aside from using a mixin template?
>
> I think this would be fixed if https://github.com/dlang/dmd/pull/11273 gets merged.

The feature still needs some work. With this PR aliases of members only works when they are declared in a function scope and not in the aggregate scope.

Example:

---
struct Inner
{
    int a;
}

struct TopLevel
{
    Inner inner;
    alias ia = inner.a;
}

void main()
{
    TopLevel tl;
    alias ia = tl.inner.a;
    ia = 42;        // OK with PR 11273
    tl.ia = 42;     // NG Error: need `this` for `a` of type `int`
}
---

I think it's not good to merge until the second case works.
Also it requires approval. For now it is specified that expressions cant be aliased.
July 19
On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant wrote:
> Here's a toy version of a problem in the wild.
>
> struct S {
>     long first;
>     union T {
>         long one;
>         double two;
>     }
>     T second;
>     alias First = first;
>     alias Second = second.one;
> }
>
> void main() {
>     S x;
>     x.First = 4;
>     x.Second = 5; // compilation error: "Error: need this for one of type long"
> }

Easiest workaround:

ref inout(long) Second() inout { return second.one; }
July 19
On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
> On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant wrote:
>> Here's a toy version of a problem in the wild.
>>
>> struct S {
>>     long first;
>>     union T {
>>         long one;
>>         double two;
>>     }
>>     T second;
>>     alias First = first;
>>     alias Second = second.one;
>> }
>>
>> void main() {
>>     S x;
>>     x.First = 4;
>>     x.Second = 5; // compilation error: "Error: need this for one of type long"
>> }
>
> Easiest workaround:
>
> ref inout(long) Second() inout { return second.one; }

Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.

July 19
On Sunday, 19 July 2020 at 12:42:47 UTC, Carl Sturtivant wrote:
> On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
>>
>> Easiest workaround:
>>
>> ref inout(long) Second() inout { return second.one; }
>
> Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.

Almost certainly no difference at all. Even DMD can inline this function:

https://d.godbolt.org/z/7ve6M8
July 19
On Sunday, 19 July 2020 at 15:00:59 UTC, Paul Backus wrote:
> On Sunday, 19 July 2020 at 12:42:47 UTC, Carl Sturtivant wrote:
>> On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
>>>
>>> Easiest workaround:
>>>
>>> ref inout(long) Second() inout { return second.one; }
>>
>> Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.
>
> Almost certainly no difference at all. Even DMD can inline this function:
>
> https://d.godbolt.org/z/7ve6M8

The alias proposal matches to the "code fast" moto. When you do object composition with several level of nesting this would be a time saver.
July 19
On Sunday, 19 July 2020 at 16:00:28 UTC, Basile B. wrote:
> On Sunday, 19 July 2020 at 15:00:59 UTC, Paul Backus wrote:
>> On Sunday, 19 July 2020 at 12:42:47 UTC, Carl Sturtivant wrote:
>>> On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
>>>>
>>>> Easiest workaround:
>>>>
>>>> ref inout(long) Second() inout { return second.one; }
>>>
>>> Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.
>>
>> Almost certainly no difference at all. Even DMD can inline this function:
>>
>> https://d.godbolt.org/z/7ve6M8
>
> The alias proposal matches to the "code fast" moto. When you do object composition with several level of nesting this would be a time saver.

It replaces something that's already a one-liner with a slightly shorter one-liner. Color me unimpressed.

Also, letting aliases refer to expressions essentially allows AST macros in through the back door. Consider the following example:

template counter()
{
    struct Counter
    {
        static size_t count;
        size_t next() { return count++; }
    }

    alias counter = Counter.init.next;
}

void main()
{
    import std.stdio: writeln;

    writeln(counter!()); // 0
    writeln(counter!()); // 1
    writeln(counter!()); // 2
}

This program compiles, runs, and prints the indicated output using the version of dmd built from the member-alias pull request [1].

Personally, I'm in favor of AST macros, but if we're going to add them to D, I think we should do it intentionally, rather than by accident, and there should be a DIP.

[1] https://github.com/dlang/dmd/pull/11273
July 19
On Sunday, 19 July 2020 at 17:06:14 UTC, Paul Backus wrote:
> Also, letting aliases refer to expressions essentially allows AST macros in through the back door. Consider the following example:
>
> [...]

Perhaps what's needed is something more that is less than allowing aliases for expressions in the wide sense you suggest here.
July 19
On 7/19/20 4:21 PM, Carl Sturtivant wrote:
> On Sunday, 19 July 2020 at 17:06:14 UTC, Paul Backus wrote:
>> Also, letting aliases refer to expressions essentially allows AST macros in through the back door. Consider the following example:
>>
>> [...]
> 
> Perhaps what's needed is something more that is less than allowing aliases for expressions in the wide sense you suggest here.

I agree. Something not yet mentioned is that aliases provide direct access to the symbols for the purposes of looking at attributes -- something that a wrapper function doesn't provide.

The question is: how do you restrict it to explicit data items within a specific aggregate without parsing arbitrary expressions?

-Steve
« First   ‹ Prev
1 2