October 13, 2021

On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:

>

I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about:

  • Worst features implemented in a non-toy language

It's a hard one. Variables implicitly declared as global in JS certainly is up there.

>
  • Worst features (in your opinion) in D

Pretty much anything working around the incompleteness of type qualifiers. @nogc, shared being a nightmare, the impossibility of having a proper container library, all stem from the same place.

>
  • Features you'd like to see in D

owned as a type qualifier. Because it would fix most of the problems for which many features have been introduced. I think we could reduce the language size overall by adding this one.

October 14, 2021
On Wednesday, 13 October 2021 at 02:39:47 UTC, Paul Backus wrote:
> On Wednesday, 13 October 2021 at 01:56:19 UTC, russhy wrote:
>> this is why things like tagged union (sumtype) and multiple return type should be implemented as language features, that way it is easier to parse (on top of other benefits)
>>
>> please push for language feature! your work on sumtype was great, but there is much more to gain from upgrading it as a language feature
>
> If anyone wants to work on a DIP and implementation for built-in sum types, they will have my full support. Unfortunately, I do not have the time or the skills necessary to lead such a project myself.

it worth doing the extra kilometer to avoid having the situation we have currently, for yet another std package

going easy road for what short term benefits? other languages have tagged union built into the language, same for nullable, it's proven to be very useful

std should serve for bigger (missing) purposes

- Filesystem package: std.fs

- Networking package: std.net

- Event Loop package: std.event

- Graphics package: std.gfx

- Datastructure package: std.collections

- Memory package: std.mem


not for little things that doesn't have any purpose other than inflating the std with tiny packages that everyone already has implemented in their own "utils" module


it's to get issues like this: https://forum.dlang.org/thread/gyzbciyzrywphxbbhdpn@forum.dlang.org

then even more no..

October 14, 2021
On Thursday, 14 October 2021 at 01:33:59 UTC, russhy wrote:
> On Wednesday, 13 October 2021 at 02:39:47 UTC, Paul Backus wrote:
>> If anyone wants to work on a DIP and implementation for built-in sum types, they will have my full support. Unfortunately, I do not have the time or the skills necessary to lead such a project myself.
>
> it worth doing the extra kilometer to avoid having the situation we have currently, for yet another std package
>
> going easy road for what short term benefits? other languages have tagged union built into the language, same for nullable, it's proven to be very useful

Sometimes the difference is not between "easy" and "hard", but between "possible" and "impossible".

If you have never written a DIP, or contributed to DMD, it is easy to underestimate the amount of work required to add a new language feature to D. I have done both, and I can say with confidence that adding built-in sum types will take *at least* 10x the effort it has taken to get std.sumtype to its current state.

I would love for D to have built-in sum types, believe me. But adding them is simply too big a project for a single volunteer like me to take on.

If you really want this to happen, I think your best bet is to convince Walter and the D Foundation to make it an official priority, and sponsor someone to work on it.
October 14, 2021
On Thursday, 14 October 2021 at 02:13:00 UTC, Paul Backus wrote:
> ...
> If you really want this to happen, I think your best bet is to convince Walter and the D Foundation to make it an official priority, and sponsor someone to work on it.

Possibly, in a parallel universe. I guess that kind of goes for most of the suggested language additions though as well which isn't very... comforting.
October 14, 2021

On Wednesday, 13 October 2021 at 20:10:06 UTC, Imperatorn wrote:

>

"Native tuples with destruction", are you sure you don't want deconstruction instead 😉

Yes, that's what I meant.

--
/Jacob Carlborg

October 14, 2021

On Wednesday, 13 October 2021 at 19:55:29 UTC, Jacob Carlborg wrote:

>
(int, int) point = (x: 2, y: 4);
auto x = point.x + a;
```

This would be better if the identifier was tied to the type.

Like below:

(int x, int y) point = (2, 4);
auto x = point.x + a;

Because with your example the following fails:

(int, int) getPoint1() { return (x: 2, y: 4); }
(int, int) getPoint2(bool shouldGetPoint1) {
  if (shouldGetPoint1) return getPoint1();

  return (left: 2, top: 4); // Possible error since the named values will be different??
}
auto point1 = getPoint1();
auto point2 = getPoint2(true);
auto point3 = getPoint2(false);

writeln("%d %d", point1.x, point1.y);
writeln("%d %d", point2.left, point2.top); // Error
writeln("%d %d", point3.left, point3.top);

However it wouldn't fail if it worked like below:

(int x, int y) getPoint1() { return (2, 4); }
(int left, int top) getPoint2(bool shouldGetPoint1) {
  if (shouldGetPoint1) return getPoint1();

  return (2, 4); // Ok
}
auto point1 = getPoint1();
auto point2 = getPoint2(true);
auto point3 = getPoint2(false);

writeln("%d %d", point1.x, point1.y);
writeln("%d %d", point2.left, point2.top); // Ok
writeln("%d %d", point3.left, point3.top);
October 14, 2021

On Thursday, 14 October 2021 at 10:55:14 UTC, bauss wrote:

>

On Wednesday, 13 October 2021 at 19:55:29 UTC, Jacob Carlborg wrote:

>
(int, int) point = (x: 2, y: 4);
auto x = point.x + a;
```

This would be better if the identifier was tied to the type.

Like below:

(int x, int y) point = (2, 4);
auto x = point.x + a;

Because with your example the following fails:

(int, int) getPoint1() { return (x: 2, y: 4); }
(int, int) getPoint2(bool shouldGetPoint1) {
  if (shouldGetPoint1) return getPoint1();

  return (left: 2, top: 4); // Possible error since the named values will be different??
}
auto point1 = getPoint1();
auto point2 = getPoint2(true);
auto point3 = getPoint2(false);

writeln("%d %d", point1.x, point1.y);
writeln("%d %d", point2.left, point2.top); // Error
writeln("%d %d", point3.left, point3.top);

However it wouldn't fail if it worked like below:

(int x, int y) getPoint1() { return (2, 4); }
(int left, int top) getPoint2(bool shouldGetPoint1) {
  if (shouldGetPoint1) return getPoint1();

  return (2, 4); // Ok
}
auto point1 = getPoint1();
auto point2 = getPoint2(true);
auto point3 = getPoint2(false);

writeln("%d %d", point1.x, point1.y);
writeln("%d %d", point2.left, point2.top); // Ok
writeln("%d %d", point3.left, point3.top);

Ofc. these are supposed to be writefln and not writeln.

October 14, 2021

On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:

>

I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about:

  • Worst features implemented in a non-toy language
  • Worst features (in your opinion) in D
  • Features you'd like to see in D

Ideas? Examples?

Thanks!

Worst features in a non-toy language. This is going to be controversial, but templates. They start innocent enough, just a way for functions to work with generic arguments. But then you build templates upon templates, and suddenly IDEs get lost, auto-refactoring stops becoming a possibility because most code doesn't exist yet, and you have to read documentation to understand what the return types and input types are of method T doStuff(T, U)(T val, U min, U max);

I wouldn't say worst, but I feel like D has many features which just don't get much use. For example contracts. Sure, they sound nice in principle, and I am sure there are some users of that feature. There's nothing wrong with that, but every feature adds more complexity and bugs to fix.

Features I'd like to see in D? Named arguments and struct/associative array initializers working outside of initialization, e.g. as function arguments.

Some syntactic sugar I like from other languages:

Named constructors as a replacement for factory static methods:

class Angle {
    this.fromDegrees(float deg) { ... }
    this.fromRadians(float rad) { ... }
}

Angle a = new Angle.fromDegrees(90.0f);

Initializer fields:

class Person
{
    string firstName, lastName;
    int age;

    this(this.firstName, this.lastName, this.age);
}
Person p = new Person("Michael", "Schumacher", 52);
October 14, 2021

On Thursday, 14 October 2021 at 11:06:00 UTC, JN wrote:

>

Named constructors as a replacement for factory static methods:

class Angle {
    this.fromDegrees(float deg) { ... }
    this.fromRadians(float rad) { ... }
}

Angle a = new Angle.fromDegrees(90.0f);

You can somewhat hack your way to it, by generating static functions at compile-time.

Of course they're not real constructors, so immutable cannot be used and you can't utilize it like new Angle.fromDegrees(90.0f) and will have to do it like Angle.fromDegrees(90.0f) instead.

Example:

class Angle {
    private:
    this(){}
    @Ctor void _fromDegrees(float deg) {
        writeln("from degrees");
    }
    @Ctor void _fromRadians(float rad) {
        writeln("from radians");
    }

    mixin NamedConstructors!Angle;
}

void main()
{
    auto a = Angle.fromDegrees(90.0f);
    auto b = Angle.fromRadians(90.0f);
}

Implementation of the hacky stuff:

struct Ctor {}

template ParametersFullyQualified(alias fun)
{
    Tuple!(string,string)[] produceIndexed(T)(T[] a, T[] b)
    {
        Tuple!(string,string)[] produced = [];

        if (a.length == b.length)
        {
            foreach (i; 0 .. a.length)
            {
                produced ~= tuple(a[i], b[i]);
            }
        }

        return produced;
    }

    enum ParametersTypeArray = Parameters!(fun).stringof[1..$-1].split(", ");
    enum ParameterNamesArray = [ParameterIdentifierTuple!(fun)];
    enum ParametersFullyQualified = produceIndexed(ParametersTypeArray, ParameterNamesArray).map!(t => t[0] ~ " " ~ t[1]).join(", ");
}

mixin template NamedConstructors(T)
{
    public:
    static:
    static foreach (member; __traits(derivedMembers, T))
    {
        static if (mixin("hasUDA!(" ~ T.stringof ~ "." ~ member ~ ", Ctor)"))
        {
            mixin(T.stringof ~ " " ~ member[1 .. $] ~ "(" ~ ParametersFullyQualified!(mixin(T.stringof ~ "." ~ member)) ~ ") { auto o = new " ~ T.stringof ~ "(); o." ~ member ~ "(" ~ [ParameterIdentifierTuple!(mixin(T.stringof ~ "." ~ member))].join(", ") ~ "); return o; }");
        }
    }
}
October 14, 2021

On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote:

> >

[...]

It's been a while i haven't used anything other than D, so i don't have much to say, i'll need to research to remember first

[...]

The enum thing works now:

```
    enum MyEnum { A, B, C}

    with(MyEnum) {
        auto e = A;
        myFunction(A);
        switch(e) {
            case A:
                break;
            default:
        }
    }
    ```