On Wed, May 11, 2022 at 06:43:39PM +0000, Guillaume Piolat via 
Digitalmars-d-learn wrote:
> On Wednesday, 11 May 2022 at 05:41:35 UTC, Ali Çehreli wrote:
> > What are you stuck at? What was the most difficult features to
> > understand? etc.
> 
>     - How to do deterministic destruction with programs that use
>     everything (struct / class / dynamic dispatch / GC / manual /
>     etc). This requires to understand what the runtime does, what the
>     gc does.

I'm not sure I fully understand what you're trying to say here. How does
GC mix with deterministic destruction?  I thought by the very nature of
GC, destruction is non-deterministic.  If you want deterministic
destruction, don't use the GC...?


>       Interesting nonetheless.
> 
>     - Some traps. Accidental TLS is a thing, top-level should probably
>     not be silently TLS.
>       People will loose hours on this completely preventable thing.
>       What was the idea, optimize code without people knowing?

Why is TLS by default a problem?

It's not really for optimization, AIUI, it's more for thread safety:
module-global state is TLS by default, so you don't accidentally
introduce race conditions.


>     - `shared static this()` vs `static this()` is another trap.

One is per-process, one is per-thread.  Why is this a trap?


[...]
>     - Some features lack an escape hatch, notably `pure`. pure leaks
>     into identifiers, like `pureMalloc`. Trying to add `pure` fails on
>     a large codebase.

IMNSHO, pureMalloc is a code smell. It should not have been added in the
first place.

But more to the point: pure is of limited utility. Perhaps the most
useful application is the initialization of immutable data structures
constructed by a mutable factory method. But other than that, I don't
find very much use for it in practice.  I wouldn't sweat it if I
couldn't easily add `pure` to an entire codebase -- it hardly makes any
difference anyway.


>     - `@safe`/`@trusted`/`@system` is good but the definition of what
>     `@trusted` means has to be remembered from the programmer.

But isn't that the nature of all escape hatches?  An escape hatch by
definition means you're operating outside of the abstractions provided
by the compiler; IOW you're on your own and you take responsibility for
any problems that you may inadvertently introduce by using the escape
hatch.


>       For example `Mutex.lock()` is `@trusted`, it could have been
>       `@system` to let user review their usage of locks. You have to
>       wonder "can a lock()/unlock() corrupt memory?". People can use
>       that to mean "@reviewed" instead. Because it is up to us, the
>       exact meaning will float in the D subcultures. A function which
>       has been marked `@trusted` does not receive any review whan
>       changed later. It will not mean the same as `@trusted` in
>       another codebase.

IMNSHO, @trusted should never be used in public-facing APIs. It's really
an implementation detail -- "this code does something using potentially
dangerous operations, but we reviewed it carefully to make sure it's
safe to call from @safe code".  The caller does NOT need to know this;
as far as the caller is concerned, it's calling a @safe function. That's
all it knows and all that it should care about. How this @safe function
is implemented -- using completely @safe operations or potentially
dangerous operations (@trusted) isn't something the user should care
about.  That's something the author of the module needs to care about,
but it's none of the users' business.

IOW, public APIs should always be @safe or @system. @trusted should only
appear on internal APIs.


>     - Generic code typically has bad names (domain-less) and worse
>     usability. It's often not pretty to look at. Mostly cultural,
>     since D has powerful templates so they had to be everywhere. UFCS
>     chains are not that convincing when you are worried about
>     maintenance.

I'm puzzled by this. I use (and write!) generic code all the time and
they have been great. UFCS chains are awesome; they allow me to express
a series of data transformations in a very concise way, so that I can
keep the high-level logic of the function readable, without having to
break it into separate functions.  This, plus `auto` type inference,
makes the code *more* maintainable, IME, because I can shuffle
components of the UFCS chain around without needing to rewrite the types
of a bunch of helper functions.

So I'm curious, what exactly is it about UFCS chains that make it less
maintainable?


>       Phobos take short names for itself, this leads to pretty
>       complicated operations having a small screen estate.

I'm also puzzled by this. Why is this a problem?


>     - `assert(false)` being different and not removed by `-release`.
>     Keyword reuse seems entrenched but honestly a "crash here" keyword
>     would be more readable.

        noreturn crashHere() { assert(false); }

        void main() {
                ...

                crashHere; // ;-)
        }


[...]
> Otherwise D is glorious and get syntax and usability right, which puts
> it ahead of almost every other language.

Can't argue with that.


T

-- 
MACINTOSH: Most Applications Crash, If Not, The Operating System Hangs

Reply via email to