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