Which language constructs could be done as a library if we accept some breaking changes?
Petar
Petar
Mon Nov 29 13:56:08 UTC 2021
On Sunday, 28 November 2021 at 20:47:28 UTC, Ola Fosheim Grøstad
wrote:
> If there was a majority in favour of D3, with breaking changes,
> and a strong focus on meta-programming, then it would make a
> lot of sense to streamline the language.
>
> [..]
>
> What do you think?
From the top of my head, my list looks like this:
1. (Perhaps not D3 worthy - can be done in D2 as well, without
removing existing funcitonality) replace all of the current
reflection functionality (`__traits(..)`, `is(..)`, `std.traits`,
etc.) with a cleaner CTFE-based API, along the lines of Stefan's
`core.reflect`:
https://github.com/UplinkCoder/druntime/tree/core_reflect/src/core/reflect
Than add syntax sugar on top, after we develop experience with
using it.
2. Type qualifiers. I really like D's type qualifiers, including
`shared`, but after using TypeScript at work for the past 2-3
years, I feel their approach is more flexible - simply offer
head-only type qualifiers and build transitive ones on top:
```ts
// Generic mapped type:
//
https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
type IdentityObject<T> = {
[K in keyof T]: T[K];
};
// Non-transitive read-only (const) type constructor
type ReadOnly<T> = {
readonly [K in keyof T]: T[K];
};
// Deep (transitive) read-only type constructor
type DeepReadOnly<T> = {
readonly [K in keyof T]: DeepReadOnly<T[K]>;
};
```
[Full example in TS
playground](https://www.typescriptlang.org/play?ssl=68&ssc=3&pln=66&pc=1#code/C4TwDgpgBACg9gSwHbALIFdhQLxQN4CwAUFFAB4BcUS6AtgEYQBOA3MaSFTQ820QL59ioSLEQoASgHkyOfOyhMIAQwAmcJABsQ5LnUasFnavt7FBxYpohYwARirxkaTHLy6odgDRRjAJigLInsAOllcABY-ISJrWz9HcWBpcPwPb18qAKCwPzC5KJYoAHpiqABhZSQkOCxlAGd6hABzJChgOCgAcjIuqEYAY2V0eugELAR6qGVFFVUAWg1tKDAmOEgmUBDLIlKoAHEIJGYEAahaZTBIVXbwCCoAC2BgMHqKUoB3L5CRCHqBpgIMDATRVZohOBMZrFdQDerFB5VVT0OBwADWxT8xQuVwgC1+9RCT1ommEdygAElVEdgOMQFJ6AArCADYAAHgAKgA+NwKADaAGkoMgoGiICA4AAzKAcgC6VA5gtlfCCVhsKwAzFQqTS6Qzmay2U4UBhgDzcO5KJ4fP5AnwwBr8pFojs4isItrqSg9UyWezjckZOa0laMrachEnVBCiUypVqrVpo0Wm0Ot1ev0WcNRsKJlMZko1IstDpVutmFsdr8oBI5lIS5zg4QSLM1EsdILhW0xRLpXKFUqVTE3WAAKxUWtqevaI1JU1N9I2rJ24hjqMxvbxmp1ZOtdqdHp9QbZsZ56athbtlZrDaV4KjkI6Z1FTdVbdJpp7tNdEBHrMjU9hXzC9i2WMtbxAbZ7zcDwNSXaM7VjWZ5gaJokGaWgaSAqB0WUEAfDQgZoDgX1WXzJRZklZgjiI25IHqHYBg0epbAANgnOsGwDecYNDeDsntVj12iJCt0TVCU33dM-yGADc2wgs5lA0sbwrSDVyEp9oxE18Ex3T9UwPX9M1knNxgUkCr3AtSoLAVjeKoODMgQwRRLfcTd0M7o7Jkk95Mmc8mKQFiqmAKCyVEfZlEw3kWxIg1gDeKAAGVEUgPllXMGJq1Sy5oAtBQADcK1OP5EmcU0MqHV11WaaKIAcA56ti0h4r9JK+QUUhm1IXqoGKzZSo6rq+pDKgw2XfgvBGvrLUc+CIkCaaW1GsaoFHeD7KmmaoFlZa+u2ls9qyxjmKwOrMISGtOJnKLMODC6Gr4R68jasi5Cqty9I-STvzexLfLk8yAsUosrNUzZ1KIF6IVIxK+QABllGCBtpIiOuR1y9ikAUfEnVRpx0AL32pCAwBKdomCqJpaWKqtyQAEQgMn8cJxsWovK9OxFHspRleUoCZlmbpATklS5aqiGIIKWKgR6tUF5mwFZhs7ogB76rsZ76sdf6plwT7dPfCSvwPPXAbMs9QcvEtr3LSGoPl2GEvqRHkYtfqSvRqgMsQvYKSQalZAM5RgHQCiRWrLpC3UW2heVkW2VyyAuQyvorOYWhximGPkHBYgnb1t2QlRobi9SDUXzjdz9N+g8M2PIGrcs23rIdnYgA).
In D3 perhaps this would like this:
```d
// aggregateOf(T) yields `struct`, `class`, `union` or
`module`
alias Const(T) = aggregateOf(T)
{
static foreach (fieldName, fieldType; T.fieldsOf)
const fieldType $fieldName;
};
alias TransitiveConst(T) = aggregateOf(T)
{
static foreach (fieldName, fieldType; T.fieldsOf)
const TransitiveConst!fieldType $fieldName;
};
```
3. Replace `interface` types and ad hoc Design-by-Introspection
patterns like `isInputRange`, `hasMember!(S1, "member")` with
TypeScript's object types:
https://www.typescriptlang.org/docs/handbook/2/objects.html which
offer a very powerful, yet elegant and concise way of describing
object shapes.
4. Replace ad hoc DIP1000 parameter storage class design with
affine types. I haven't given it much thought, but ideally we
should be able to write an Affine type constructor in library
code and simply use it like as any other type constructor (e.g.
tuple, sum type, etc.)
5. Introduce some concept of compile-time dependency resolution /
context abstraction (see
https://docs.scala-lang.org/scala3/reference/contextual.html) so
that things like the current allocator, scheduler,
request/response context, etc., can be implicitly provided to
improve the ergonomics of such APIs. For example, one could
specify that in one scope the current implementation of
associative arrays is a GC-managed hashmap, while in other a
unique_ptr to red-black tree value container, like `std::map`,
all while using the same `K[V] x = [key1: value1]` syntax.
More information about the Digitalmars-d
mailing list