On Thu, 29 Aug 2024 at 01:21, Nick Treleaven via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On Wednesday, 28 August 2024 at 11:47:12 UTC, Manu wrote:
> For instance, the evidence here:
> __traits(getParamterStorafeClasses,
> function, paramterByIntegerIndex)
> How would you expect to detect if something is ref, or scope,
> or whatever?

__traits(isRef, x)

I expect a trait for isScope could be added if needed.

Did you miss my point? The language can't express these things... we need backdoor information to hold the concept in any sort of expression.

> Of course, what you expect is a STRING LITERAL, which you can
> compare to a
> string of the name of the storage class.
> There's no stronger evidence that storage classes are
> themselves such a
> broken idea that exist way outside of the language than passing

Just because you can't e.g. alias a storage class doesn't mean it
is 'outside' the language. It's part of a declaration.

You didn't miss my point. Hmmm.

> around
> string literals to tell you a fact about some declaration.
> C++ puts these things in the type, and while that creates some
> awkward
> cases, it's infinitely better than what we have in D in terms of
> expressiveness and flexibility in terms of meta programming.

I've heard that C++ references are a complete swamp of special
cases (regardless of lvalue vs rvalue reference).

You've "heard"? I'm sorry, but your qualification to comment on the topic is definitely problematic from here on...

Anyone who holds the opinion that C++ references are a swamp of special cases by contrast has clearly not had any comparable experience with D references (and additional *suite* of storage classes). Nobody with experience in this matter can honestly say with a straight face that C++ is complicated and edgy by direct comparison.
Nothing in D is more awkward or poorly expressed.

> What's kinda funny, is that your link to the cool ref-local
> feature (finally!) above will be shortly followed with "how do
> I detect if a local is a reference?" ... there's no
> __traits(getLocalVariableStorageClass, ...)

__traits(isRef, x)

Example with `auto ref` in the changelog.

Okay, fair; I had my mind on the general query relating to storage class like the one that returns a list of strings for each parameter. But it's like you say "one could be added for scope"; which actually demonstrates my point equally well.
... and why do we have 2 ways that do exactly the same thing?

C++ just doesn't have any of this nonsense. My biggest sense of loss from C++ to D is this fundamental area of the language in D that exists outside the language, and requires hacks and general weird-shit to access.

> So I still don't really know; what IS a ref?

It's a pointer that is automatically dereferenced on use, and
never does pointer arithmetic.

No, that's what it does. Write me an expression that embodies the concept? Write me an expression that copies ref-ness from one declaration to another declaration, for instance; I might be synthesising a parameter list for a shim with information from a given function...
It can't be expressed in the language. It's just an internal compiler concept that's unbelievably awkward to reason about, and can only be reasoned with back-door information.

Have you had a look at core.lifetime recently? Take a look at C++'s implementation of `std::forward`, `std:: move`, `emplace` (aka placement new)... tell me the situation in D is superior... core.lifetime is a war zone; you'll get a really good signal of just how far off the mark we have landed when comparing those fundamental language primitives.
There's basically nothing lower in the concept stack than core.lifetime; so why is it a complete mess? The reason is because none of our core concepts fit together; D is made out of parts with seriously jagged edges, and it needs a flood of hacky special-case reasoning to resolve the problems at the lowest level.

D's advantage is that a lot of things ARE POSSIBLE, but they come at a massive intellectual cost, and it doesn't need to be that way. It shouldn't be that way.

> It's astonishing that s.tupleof is a sequence of ref's as you
> say...

BTW that was just how I understand `.tupleof`. I see it as (a
superset of) a sequence of implicit ref declarations.

Okay, so you might be wrong? Whether you are or aren't is irrelevant though, this is further evidence of the problem... it's not a "reasonable" design in fundamental terms. It's actually quite literally anti-reasonable. It's just internal compiler magic; the whole thing is a big special case, which creates edge cases at almost every single point of contact.
If you need a __traits to know a fundamental primitive fact like ref, something already went wrong.

> does anything else in the language have a semantic like that?
> How could I synthesise something like that from anything else
> if I wanted to?

If you mean synthesize `tupleof`, I already showed how (without
introspection support), the first example here:
https://forum.dlang.org/post/fctetiyhbiyhadlmcyzr@forum.dlang.org

That example literally works with dmd recent git.

I'm very keen to play with ref locals when it lands; it's been such a long time coming.
That's not quite the same thing though; you've declared 2 local variables; does that infer they allocate stack space? Do I rely on the optimiser now to remove them? It looks like yet-another-workaround/hack to me.