October 25, 2021

On Sunday, 24 October 2021 at 22:44:39 UTC, Paul Backus wrote:

>

That explains why someone accustomed to mature tooling might choose to avoid D entirely. I do not think it explains the behavior described in [this post by Gavin Ray][1], which is what I was responding to.

I think there is a shift in how people expect to learn, reducing cognitive load and providing easy navigation makes the process less frustrating.

October 25, 2021
>

If you could make any changes to D, what would they look like?

It's a great thing other people get to decide, because I would remove:

  • pure
  • shared
  • @property
  • inout
  • GC-calling-destructors
  • virtual-by-default
  • real
  • synchronized
  • inout
  • alias this
  • and parts of Phobos too.

But D is also about catering to many different people.

October 25, 2021

On Monday, 25 October 2021 at 13:42:19 UTC, Guillaume Piolat wrote:

>

It's a great thing other people get to decide, because I would remove:

  • pure
  • shared
  • @property
  • inout
  • GC-calling-destructors
  • virtual-by-default
  • real
  • synchronized
  • inout
  • alias this
  • and parts of Phobos too.

But D is also about catering to many different people.

Finally a post that made me wake up from my sleep. Interesting I agree with most of it.

>
  • pure

Agreed, if you don't want a function messing around with a global state, don't mess around with a global state, easy. You don't need a badge for that. I'm sure there are holes in the pure rule that the compiler cannot detect as well.

>
  • shared

Agreed, shared is one of the biggest mess in D. This is where it is obvious where the D language designers lack in experience and knowledge. It is also a very complex issue so my advice is to rather to copy an existing design or not at all and rely more on manual concurrent "safety".

>
  • @property

Do we need it? Isn't this partly handled by UFCS.

>
  • inout

Isn't this depreciated?

>
  • GC-calling-destructors

GC calling destructors is often not used. However, there might be rare occasions we need it. Like knowing when something is being destroyed.

>
  • virtual-by-default

Agreed, it should be final by default. This one of the rare occasions where the D maintainers agree.

>
  • real

Agreed, real can be removed. Even Intel doesn't optimize their old FPU anymore and SSE is used instead. There might be rare occasions where we should use old Intel FPU, like embedded Pentium clones but these are rare themselves.

>
  • synchronized

I kind of like the idea with synchronized classes. I don't think it is that hard to implement and could be a neat thing. Also helps Java portability.

>
  • alias this

Agreed, alias this should be removed and mixin templates should be used instead.

>
  • and parts of Phobos too.

You have to be more specific about this one.

October 25, 2021

On Monday, 25 October 2021 at 13:42:19 UTC, Guillaume Piolat wrote:

> >

If you could make any changes to D, what would they look like?

It's a great thing other people get to decide, because I would remove:

  • pure
  • shared
  • @property
  • inout
  • GC-calling-destructors
  • virtual-by-default
  • real
  • synchronized
  • inout
  • alias this
  • and parts of Phobos too.

But D is also about catering to many different people.

Apart from pure, I agree with everything on that list, and would even add a bunch of things:

  • Module constructors
  • lazy parameters
  • in / out parameters
  • in / out contracts
  • Function body literals ({} instead of () {})
  • Typesafe Variadic Functions (foo(int[] a...))
  • String literals starting with q
  • The remaining octal literals (00-07)
  • is() expressions
  • switch with run-time variable cases
  • switch with string cases
  • alias reassignment
  • __traits(compiles)
  • opDispatch
  • opCall
  • opApply
October 25, 2021

On Monday, 25 October 2021 at 14:52:55 UTC, Dennis wrote:

>
  • Module constructors
  • lazy parameters
  • in / out parameters
  • in / out contracts
  • Function body literals ({} instead of () {})
  • Typesafe Variadic Functions (foo(int[] a...))
  • String literals starting with q
  • The remaining octal literals (00-07)
  • is() expressions
  • switch with run-time variable cases
  • switch with string cases
  • alias reassignment
  • __traits(compiles)
  • opDispatch
  • opCall
  • opApply

You agree with 9 of my 10 proposals.
I agree with only about 10 of your 16 proposals.
It's easy to see why this is a bit hard to remove things in practice. :)

October 25, 2021
On Monday, 25 October 2021 at 14:52:55 UTC, Dennis wrote:
> Apart from `pure`, I agree with everything on that list, and would even add a bunch of things:

Damn, like do you actually use *any* D features?
October 25, 2021

On Wednesday, 20 October 2021 at 09:47:54 UTC, SealabJaster wrote:

>

Just for giggles, without pesky things like breaking changes; rational thinking, logical reasoning behind the changes, etc.

What interesting changes would you make to the language, and what could they possibly look like?

Forgetting "rational thinking, logical reasoning behind the changes" - how? Isn't it all rational reasoning in programming language design - if we leave it out, what's left? I don't know what you meant, so rest of my reply just ignores that part.

The answer is, probably not too much after all. If I really want to change something, I can write a DIP. So far I've written only one.

Now of course, if I could forget about breaking changes, I could propose things I wouldn't otherwise. And I think you meant I could do the changes without bothering with the DIPs, so I would have more power than I do. But still - I think the DIP process keeps me honest on what I really am ready to bother on, so I don't think I would change that much stuff even if I could just write a spec piece and have it automatically accepted.

Now, were I a full-time BDFL so that I would spend all day on the question, some changes I might do:

  • Revise @safe by default DIP so that @safe foreign language declarations would deprecated but not immediately removed. One more review and then accept it unless a major flaw is found.

  • Write a DIP: short integer types auto-promoted to int/uint are implicitly convertible back to original type within the same expression. I've been toying with the idea.

  • Accept Dennis's unit type DIP when it hits the the formal assessment.

  • Accept preview=shortenedMethods DIP when it hits the the formal assessment.

  • Write a DIP for preview=in and accept it unless a major flaw is found (yet I haven't wrote one IRL).

  • Phobos should strive to be more decoupled from the compiler and runtime. Using internal DRuntime features should not be allowed, and the compiler should be able to compile older Phobos releases (Haven't tested if this is the case TBH).

  • There's a dead letter in the spec that says that (x) @trusted => {/*...*/} pattern is allowed only if the lambda is safe regardless of the value of the argument and the surrounding context. I'd remove that rule.

  • Move the ImportC section from the spec to the DMD manual.

  • Declaration against the version(Something) /*...*/ else static assert(0, "not supported"); pattern in Phobos and DRuntime. Just compile what is implemented and leave other stuff out, instead of failing compilation.

  • Avoid adding anything major into language without a DIP. I would allow myself to write it if no-one volunteers to champion the DIP.

Well, It turns out I didn't shake the question of backwards compatibility after all. I guess it's because I want to consider it - backwards compatibility is part of my D dream.

October 25, 2021

On Monday, 25 October 2021 at 16:04:12 UTC, Dukc wrote:

>
  • There's a dead letter in the spec that says that (x) @trusted => {/*...*/} pattern is allowed only if the lambda is safe regardless of the value of the argument and the surrounding context.

Meant (x) @trusted {/*...*/}

October 25, 2021
On Mon, Oct 25, 2021 at 02:34:24PM +0000, IGotD- via Digitalmars-d wrote:
> On Monday, 25 October 2021 at 13:42:19 UTC, Guillaume Piolat wrote:
> > It's a great thing other people get to decide, because I would remove:
[...]
> > - pure
> 
> Agreed, if you don't want a function messing around with a global state, don't mess around with a global state, easy. You don't need a badge for that. I'm sure there are holes in the pure rule that the compiler cannot detect as well.

I think the idea behind pure is for the compiler to enforce purity in your code, since human beings are prone to making mistakes.  And also to optimize code in certain cases, though in practice that's so rare that it's not really that useful (IIRC, the only optimization currently performed applies only to strongly pure functions, and within a single expression, so that `f(x) + f(x)` calls `f` only once if f is strongly pure.

Well, pure is also used in implicit casting to immutable in functions that construct objects. But this is also relatively rare and somewhat low impact.

So I'm on the fence about `pure` in D. It promises a lot, but the current implementation is lackluster, and delivers only a little. If it had a bigger impact on optimization, say, it could be more useful. But currently its impact in practice is rather niche, and most of the time doesn't really affect much in code. (Perhaps except to generate annoying compile errors when something expects to be pure but isn't!)


> > - shared
> 
> Agreed, shared is one of the biggest mess in D. This is where it is obvious where the D language designers lack in experience and knowledge. It is also a very complex issue so my advice is to rather to copy an existing design or not at all and rely more on manual concurrent "safety".

Agreed.


> > - @property
> 
> Do we need it? Isn't this partly handled by UFCS.

@property was incompletely implemented, lacks a clear vision, and currently is basically just bitrotting.  With UFCS and optional parentheses, plus some questionable designs (i.e., `a.x = y` is rewritten as `a.x(y)` under some circumstances), @property is basically redundant and affects very little. The only concrete case I can think of where it actually makes a difference is when you have a property function that returns by ref and the caller tries to take the address. Well, that and isInputRange stubbornly insists on @property even though it technically doesn't need to.

So yeah, niche use, incomplete implementation, low impact.  Meh. Wouldn't miss it if it went the way of the dodo.


> > - inout
> 
> Isn't this depreciated?

Not that I know of.  And yeah, it's a mess. Very convenient in the simple cases, a nightmare to work with in non-trivial cases due to complicated interactions with the rest of the type system and incomplete functionality in that area.


> > - GC-calling-destructors
> 
> GC calling destructors is often not used. However, there might be rare occasions we need it. Like knowing when something is being destroyed.

GC and dtors are just bad news in general... unless you don't care when something is destroyed (if ever), just that fact that it was destroyed.


> > - virtual-by-default
> 
> Agreed, it should be final by default. This one of the rare occasions where the D maintainers agree.

Unfortunately this can't be changed without subtle breakage of a whole ton o' code.  So, sadly, not gonna happen.


> > - real
> 
> Agreed, real can be removed. Even Intel doesn't optimize their old FPU anymore and SSE is used instead. There might be rare occasions where we should use old Intel FPU, like embedded Pentium clones but these are rare themselves.

Real is nice in those rare circumstances where (1) the extra precision
actually make a difference, and (2) the performance hit doesn't kill
you.  But yeah, it's not the best thing there is.  Part of the problem
is how std.math greedily converts to real and back (though IIRC this has
been (partially?) fixed in recent releases).

Also, it's the one type in D that doesn't have a fixed width, which can lead to surprising results in cross-platform code (though, admittedly, only rarely).


> > - synchronized
> 
> I kind of like the idea with synchronized classes. I don't think it is that hard to implement and could be a neat thing. Also helps Java portability.

It's convenient for quick-n-dirty concurrent OO code where performance isn't critical. But if you want more modern concurrent techniques / high performance, yeah, it's not of much use.  It's arguably dated technology.


> > - alias this
> 
> Agreed, alias this should be removed and mixin templates should be used instead.
[...]

`alias this` is awesome for refactoring code, though. When you want to substitute a new type for an existing one and want code that expect only the old type to work without a truckload of rewriting.

But yeah, beyond a rather narrow scope of usefulness, it quickly leads to poor maintainability and other code smells.


T

-- 
Дерево держится корнями, а человек - друзьями.
October 25, 2021
On Mon, Oct 25, 2021 at 02:52:55PM +0000, Dennis via Digitalmars-d wrote: [...]
> - Module constructors

Module ctors are da bomb!  You can do all sorts of awesome things with them, if you know how to combine them with compile-time introspection and other metaprogramming techniques.  It's part of why Adam's jni.d module is so awesome.


> - `lazy` parameters

I rarely need this, so meh.  I guess it's nice to have when you do need it, but so far I haven't.


> - `in` / `out` parameters

IMO these are very useful.


> - `in` / `out` contracts

These too, except the implementation could be improved.


> - Function body literals (`{}` instead of `() {}`)

One can argue about syntax till the cows come home, and we wouldn't come to an agreement. :D


> - Typesafe Variadic Functions (`foo(int[] a...)`)

These are awesome!  Lets you construct array arguments on the stack where a function accepting only an array would force a GC (or other) allocation.


> - String literals starting with `q`

Heredoc literals are awesome, I use them all the time.  They make code-generating code actually readable, instead of being candidate submissions for the IOCCC. :-/

Though I can see how the proliferation of different string literals make the D spec somewhat unwieldy...


> - The remaining octal literals (00-07)

Yeah, kill octals with fire and extreme prejudice. :->


> - `is()` expressions

Yeah they are a mess. Well, not so bad once you understand the logic behind them, but still, they're very opaque for a newcomer.  And there's also the odd hidden dark corner that will make even a seasoned D veteran cringe, e.g.:

	https://forum.dlang.org/thread/vpjpqfiqxkmeavtxhyla@forum.dlang.org

But is() expressions are also the backbone of much of D's metaprogramming prowess, so unless you come up with something better, they are here to stay.


> - `switch` with run-time variable cases

Yeah... I generally avoid using switches in that way. It just makes code hard to read.


> - `switch` with string cases

This is actually nice for some cases.  But the current implementation involves instantiating a template potentially with a huge number of arguments (*ahem*cough*std.datetime*ahem*), which at one point caused so much grief we had to rewrite either std.datetime or the druntime implementation of the string switch, I forget which.


> - `alias` reassignment

Whaddya mean, that's one of the best things to happen to D lately, that gets rid of a whole bunch of evil recursive templates from druntime and Phobos.


> - `__traits(compiles)`

Yeah, this one's a loaded gun.  It seems a good idea on the surface, until you realize that most (all?) of the time, you actually don't *mean* "does this code compile"; usually you have something much narrower in scope like "does X have a member named Y" or "is X callable with Y as argument".  Using __traits(compiles) for this quickly leads to the problem where you *can* call X with Y, or X does have a member named Y, etc., but there's a typo somewhere in the code that makes it non-compilable, so suddenly your template overload resolution goes in a completely unexpected direction generating screenfuls of completely unhelpful and irrelevant errors.


> - `opDispatch`

opDispatch is awesome. See: Adam's jni.d.


> - `opCall`

opCall is needed for function objects. How else are you supposed to reify functions when you need to?!


> - `opApply`

This is actually useful in cases where the range API may not be the best way to do things (believe it or not, there *are* such cases). One example is iterating over a tree without needing to allocate more memory for the iteration.


T

-- 
My program has no bugs! Only undocumented features...