May 30, 2015
On Saturday, 30 May 2015 at 00:50:39 UTC, Steven Schveighoffer wrote:
> I suggest first we build a library AA that sits beside real AA, even if it doesn't . Then we create a test suite to prove that the library AA can be a drop in replacement. Then replace it :)

Writing the AA is NOT the problem, but I doubt we can get compatible enough to replace the built-in AA. Rather it'll require to deprecate a few built-in AA semantics and adding operator and literal extensions for the library type.
Hence the proposal to start with a HQ library AA and incrementally converge them.
May 30, 2015
On Saturday, 30 May 2015 at 01:32:26 UTC, IgorStepanov wrote:
>> - attributes
> We will able to deprecate attribute violations in transitional version (with vtbl).

Yes, we'd have to deprecate attribute issues of the built-in AA before we can switch.
Maybe that's already to disruptive.

>> - literals (especially polysemous initializers, i.e. ubyte[ubyte] aa = [0:1, 1:2])
> Yes, this is the first main trouble.

We could possibly make the array of types polysemeous as well and deduce the type from the constructor argument.

>> - implicit tail const conversion Val[Key] -> const(Val)[Key]
> May be we may add "alias this"-es for all all those variants?
> Something like ...
> struct AA(K, V)
> {
>     alias getCKeyMval this;
>     alias getMKeyCval this;
>     alias getCKeyCval this;
>     @property {
>     ref AA!(const(K), V) getCKeyMval() { return *cast(typeof(return)*)&this; }
>     ref AA!(K, const(V)) getMKeyCval() { return *cast(typeof(return)*)&this; }
>     ref AA!(const(K), const(V)) getCKeyCval() { return *cast(typeof(return)*)&this; }
>     }
> }

"overload" by return type? Maybe.

> We should start to try to find and solve them.

The list is pretty long, there are lots of unknowns.
I'd rather choose an incremental approach that allows for intermediate failure.
May 30, 2015
On Friday, 29 May 2015 at 22:41:13 UTC, Martin Nowak wrote:
>> 2. What issues disallows us to implement full library AA?
>> Except .stringof, .mangleof, and other compiler magic.
>> I see only two issues: opIndexCreate and building aa from
>> literals.
>
> - error messages
> - attributes
> - literals (especially polysemous initializers, i.e.
> ubyte[ubyte] aa = [0:1, 1:2])
> - implicit tail const conversion Val[Key] -> const(Val)[Key]
> - lots of magic around making Key const
> - delete aa[key]
> - lots of other small details (grep for Taarray in
> src/expression.c)
>
> This is a heavily used built-in type, we can't risk a rewrite that breaks lots of code.

Not sure how much this is a problem but implicit conversion from null may also be an issue: http://localhost/post/asvcbsvfcxznwypttojk@192.168.0.1
May 30, 2015
On Saturday, 30 May 2015 at 08:50:21 UTC, Vladimir Panteleev wrote:
> http://localhost/post/asvcbsvfcxznwypttojk@192.168.0.1

Sorry, working link: http://forum.dlang.org/post/asvcbsvfcxznwypttojk@192.168.0.1
May 30, 2015
On Saturday, 30 May 2015 at 08:51:31 UTC, Vladimir Panteleev wrote:
> On Saturday, 30 May 2015 at 08:50:21 UTC, Vladimir Panteleev wrote:
>> http://localhost/post/asvcbsvfcxznwypttojk@192.168.0.1
>
> Sorry, working link: http://forum.dlang.org/post/asvcbsvfcxznwypttojk@192.168.0.1

We may say that AA!(K, V)* should be recognized as V[K] by compiler. However in this case we will found another problem: opIndexAssign will unable to allocate memory for the new AA instance, because it can't modify `this` pointer.
Otherwise, implicit casting _from_ another type is a unsolvable task now.
Please, remind, why we don't want to add possibility of implicit casting from another type (not as default constructor behaviour, of course)?
Something like

struct Foo
{
    int a;
    static Foo opImplicitConstructFrom(T)(T val) if(is(T : int))
    {
        return Foo(val);
    }
}
May 30, 2015
> struct Foo
> {
>     int a;
>     static Foo opImplicitConstructFrom(T)(T val) if(is(T : int))
>     {
>         return Foo(val);
>     }
> }

void test(Foo foo, int i)
{
    assert(foo.a == i);
}

test(42, 42); ->
test(Foo.opImplicitConstructFrom(42), 42);
May 30, 2015
On Saturday, 30 May 2015 at 14:10:35 UTC, IgorStepanov wrote:
>     static Foo opImplicitConstructFrom(T)(T val) if(is(T : int))

I briefly mentioned this at the dconf and thinking about it a bit more, I think there's only two cases where we want implicit construction: function argument lists and function return values. (The syntax doesn't really matter, but I'd do it similar to C++ and just slap an @implicit on a regular constructor).


So:

struct Foo { @implicit this(typeof(null)) {} }

Foo test() {
   return null;
}

Right now, that return null would say "cannot implicitly convert null to Foo". But since it is on a return statement and we have an implicit constructor, it would automatically rewrite that to return Foo(null); and be happy with it.

Note that this does NOT change

Foo foo = null;

because that already works with a standard constructor today! Similarly, foo = null is handled with opAssign. So no change needed there.



Anyway, the trickier case is function calls:


void test(Foo) {}

test(null); // should do test(Foo(null));



How does that interact with operator overloading? (I'd note that C++ does this so we could always borrow their rules too.) My proposal would be that if something matches exactly without implicit conversion, use that. Otherwise, try the implicit construction and issue an error if more than one match.


This would work the same as arrays today:

void a(int[]) {}
void a(long[]) {}
void a(typeof(null)) {}

void main() { a(null); }


That compiles. Comment the third line though and get:

b.d(5): Error: b.a called with argument types (typeof(null)) matches both:
b.d(1):     b.a(int[] _param_0)
and:
b.d(2):     b.a(long[] _param_0)



So I think that's doable and shouldn't break any existing code as it is a new opt-in keyword. Just will have to watch for regression bugs...


But that'd take care of the null problem with library AAs.... and I could use it to make my var type all the more wild :P
May 30, 2015
On Saturday, 30 May 2015 at 15:24:49 UTC, Adam D. Ruppe wrote:
> On Saturday, 30 May 2015 at 14:10:35 UTC, IgorStepanov wrote:
>>    static Foo opImplicitConstructFrom(T)(T val) if(is(T : int))
>
> I briefly mentioned this at the dconf and thinking about it a bit more, I think there's only two cases where we want implicit construction: function argument lists and function return values. (The syntax doesn't really matter, but I'd do it similar to C++ and just slap an @implicit on a regular constructor).
>
>
> So:
>
> struct Foo { @implicit this(typeof(null)) {} }
>
> Foo test() {
>    return null;
> }
>
> Right now, that return null would say "cannot implicitly convert null to Foo". But since it is on a return statement and we have an implicit constructor, it would automatically rewrite that to return Foo(null); and be happy with it.
>
> Note that this does NOT change
>
> Foo foo = null;
>
> because that already works with a standard constructor today! Similarly, foo = null is handled with opAssign. So no change needed there.
>
>
>
> Anyway, the trickier case is function calls:
>
>
> void test(Foo) {}
>
> test(null); // should do test(Foo(null));
>
>
>
> How does that interact with operator overloading? (I'd note that C++ does this so we could always borrow their rules too.) My proposal would be that if something matches exactly without implicit conversion, use that. Otherwise, try the implicit construction and issue an error if more than one match.
>
>
> This would work the same as arrays today:
>
> void a(int[]) {}
> void a(long[]) {}
> void a(typeof(null)) {}
>
> void main() { a(null); }
>
>
> That compiles. Comment the third line though and get:
>
> b.d(5): Error: b.a called with argument types (typeof(null)) matches both:
> b.d(1):     b.a(int[] _param_0)
> and:
> b.d(2):     b.a(long[] _param_0)
>
>
>
> So I think that's doable and shouldn't break any existing code as it is a new opt-in keyword. Just will have to watch for regression bugs...
>
>
> But that'd take care of the null problem with library AAs.... and I could use it to make my var type all the more wild :P

This would also greatly improve Variant and Algebraic
May 30, 2015
On Saturday, 30 May 2015 at 15:24:49 UTC, Adam D. Ruppe wrote:
> On Saturday, 30 May 2015 at 14:10:35 UTC, IgorStepanov wrote:
>>    static Foo opImplicitConstructFrom(T)(T val) if(is(T : int))
>
> I briefly mentioned this at the dconf and thinking about it a bit more, I think there's only two cases where we want implicit construction: function argument lists and function return values. (The syntax doesn't really matter, but I'd do it similar to C++ and just slap an @implicit on a regular constructor).
What did people say about this idea?

June 20, 2015
On 05/30/2015 10:50 AM, Vladimir Panteleev wrote:
> Not sure how much this is a problem but implicit conversion from null may also be an issue: http://localhost/post/asvcbsvfcxznwypttojk@192.168.0.1

Not in my proposal, b/c it's an explicit conversion that does allocate a translation wrapper.

https://github.com/D-Programming-Language/druntime/pull/1282/files?diff=unified#diff-7f36fe9957b2e56c0c468548c4e1b0aaR167