Thread overview
The worst overload system that actualy works
Dec 21, 2020
Basile B.
Dec 21, 2020
Timon Gehr
Dec 21, 2020
Basile B.
Dec 21, 2020
Timon Gehr
Dec 21, 2020
sighoya
Dec 21, 2020
Basile B.
Dec 23, 2020
Basile B.
December 21, 2020
Overloads can be confusing because of implict conversions and promotion rules.
So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.

[1] https://styx-lang.gitlab.io/styx/overload_declaration.html



December 21, 2020
On 21.12.20 14:35, Basile B. wrote:
> Overloads can be confusing because of implict conversions and promotion rules.
> So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.
> ...

Proposing this for D would not do much. This is already in D:

void createFromBytes(ubyte[] values) {}
void createFromFile(string name)     {}

alias create = createFromBytes;
alias create = createFromFile;

void main(){
    const string name = "test.txt";
    create(name); // calls createFromFile
}

:P
December 21, 2020
On Monday, 21 December 2020 at 16:48:27 UTC, Timon Gehr wrote:
> On 21.12.20 14:35, Basile B. wrote:
>> Overloads can be confusing because of implict conversions and promotion rules.
>> So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.
>> ...
>
> Proposing this for D would not do much. This is already in D:
>
> void createFromBytes(ubyte[] values) {}
> void createFromFile(string name)     {}
>
> alias create = createFromBytes;
> alias create = createFromFile;
>
> void main(){
>     const string name = "test.txt";
>     create(name); // calls createFromFile
> }
>
> :P

yeah but I think the way the overloads are tried is different.
December 21, 2020
On 21.12.20 17:59, Basile B. wrote:
> On Monday, 21 December 2020 at 16:48:27 UTC, Timon Gehr wrote:
>> On 21.12.20 14:35, Basile B. wrote:
>>> Overloads can be confusing because of implict conversions and promotion rules.
>>> So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.
>>> ...
>> ...
> 
> yeah but I think the way the overloads are tried is different.

So what you don't mean to propose for D is to try overloads in order, ignoring implicit conversions. Makes sense.
December 21, 2020
On Monday, 21 December 2020 at 13:35:10 UTC, Basile B. wrote:
> Overloads can be confusing because of implict conversions and promotion rules.
> So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.
>
> [1] https://styx-lang.gitlab.io/styx/overload_declaration.html

But they need anyway overload resolution for this.

The advantage is that method could be assigned to more than one overloaded set (multi method).

The disadvantage is the manual disambiguation of method names by defining their types.
That sucks and they can't always be demangled in meaningful way than simply enumerating their param types.

I find explicit implicit converions in D useful, but I didn't appreciate how overload resolution handles this that much.
December 21, 2020
On Monday, 21 December 2020 at 19:36:22 UTC, sighoya wrote:
> On Monday, 21 December 2020 at 13:35:10 UTC, Basile B. wrote:
>> Overloads can be confusing because of implict conversions and promotion rules.
>> So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.
>>
>> [1] https://styx-lang.gitlab.io/styx/overload_declaration.html
>
> But they need anyway overload resolution for this.

Yes but it's simple. If Indentifier resolution gives an overload set  then the set members are tried, e.g O(n).

https://gitlab.com/styx-lang/styx/-/blob/master/src/styx/semantic/expressions.d#L395

>
> The advantage is that method could be assigned to more than one overloaded set (multi method).
>
> The disadvantage is the manual disambiguation of method names by defining their types.
> That sucks and they can't always be demangled in meaningful way than simply enumerating their param types.
>
> I find explicit implicit converions in D useful, but I didn't appreciate how overload resolution handles this that much.


December 22, 2020
On Monday, 21 December 2020 at 13:35:10 UTC, Basile B. wrote:
> Overloads can be confusing because of implict conversions and promotion rules.
> So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.
>
> [1] https://styx-lang.gitlab.io/styx/overload_declaration.html

I know that semantics was perhaps the main point of your post, but I must say that I have never thought that overloading can have an explicit syntax and I like it a lot :)

Even from a developer maintenance, and likely compiler implementation point of view, I think it's a good property to only allow overloading with an explicit syntax, as that way you can assume that all symbol declarations names in a module/namespace are unique, as overloading can't happen by accident. And using "Go to definition" in an IDE will always point you to right location. And just in general it's less error prone and on the good side of explicit vs verbose ;)

The last few months we mainly use TypeScript at work, and I'm really fond of their type aliases syntax (like D aliases, but more powerful):
https://www.carlrippon.com/when-to-use-type-aliases-v-interfaces/
https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases

So, if it was me, I'd I use an assignment syntax like this:

alias create = overload(
    createFromBytes,
    createFromFile,
);


Where `overload` is a symbol constructor (just like `*`, `[]` `const`, `shared` are type constructors in D).

Hmm, re-reading the example, I think we can even implement it in pure D:

alias create = overload!(
    createFromBytes,
    createFromFile,
);

template overload(symbols...)
{
    static foreach (sym; symbols)
        alias overload = sym;
}

Of course, we still leave the actual overload resolution to the compiler, but if necessary, we can easily implement it like this:

template overload(functions...)
{
    auto ref overload(Args...)(auto ref Args args)
    {
        static foreach (fun; functions)
        {{
            static if (__traits(compiles, () => fun(args)))
                return fun(args);
        }}
    }
}

(^ Not tested, so there may be bugs, but it should be enough to show the idea).

So dare I say, we can deprecate implicit overloading in D with a workable migration path to something like this :O
December 23, 2020
On Tuesday, 22 December 2020 at 21:14:07 UTC, Petar Kirov [ZombineDev] wrote:
> On Monday, 21 December 2020 at 13:35:10 UTC, Basile B. wrote:
>> Overloads can be confusing because of implict conversions and promotion rules.
>> So here are the explicit overloads[1]. Note that there is no plan to propose this for D ;)... destroy.
>>
>> [1] https://styx-lang.gitlab.io/styx/overload_declaration.html
>
> I know that semantics was perhaps the main point of your post, but I must say that I have never thought that overloading can have an explicit syntax and I like it a lot :)
>
> Even from a developer maintenance, and likely compiler implementation point of view, I think it's a good property to only allow overloading with an explicit syntax, as that way you can assume that all symbol declarations names in a module/namespace are unique, as overloading can't happen by accident. And using "Go to definition" in an IDE will always point you to right location. And just in general it's less error prone and on the good side of explicit vs verbose ;)

To make it less verbose it should be possible to use an attribute, e.g

  @overload("create") createFromStuff();

Although then there's a loose of control on the manual ordering.

> The last few months we mainly use TypeScript at work, and I'm really fond of their type aliases syntax (like D aliases, but more powerful):
> https://www.carlrippon.com/when-to-use-type-aliases-v-interfaces/
> https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases
>
> So, if it was me, I'd I use an assignment syntax like this:
>
> alias create = overload(
>     createFromBytes,
>     createFromFile,
> );
> Where `overload` is a symbol constructor (just like `*`, `[]` `const`, `shared` are type constructors in D).
>
> Hmm, re-reading the example, I think we can even implement it in pure D:
>
> alias create = overload!(
>     createFromBytes,
>     createFromFile,
> );
>
> template overload(symbols...)
> {
>     static foreach (sym; symbols)
>         alias overload = sym;
> }
>
> Of course, we still leave the actual overload resolution to the compiler, but if necessary, we can easily implement it like this:
>
> template overload(functions...)
> {
>     auto ref overload(Args...)(auto ref Args args)
>     {
>         static foreach (fun; functions)
>         {{
>             static if (__traits(compiles, () => fun(args)))
>                 return fun(args);
>         }}
>     }
> }
>
> (^ Not tested, so there may be bugs, but it should be enough to show the idea).

Nice. Fixed:

---
struct overload(functions...)
{
    static auto opCall(Args...)(auto ref Args args)
    {
        static foreach (fun; functions)
        {{
            static if (__traits(compiles, () => fun(args)))
                return fun(args);
        }}
    }
}

alias MySet = overload!()...
---

only problem is that it does not support member func (+ the infamous not reachable
thing) but well, I get that this was more a joke.

> So dare I say, we can deprecate implicit overloading in D with a workable migration path to something like this :O