Timon Gehr
Posted in reply to Dr Machine Code
| On 14.11.21 22:54, Dr Machine Code wrote:
> On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:
>> On 10/11/21 5:59 PM, Atila Neves wrote:
>>> ...
>> ...
>>
>>> * Features you'd like to see in D
>>
>> - built-in tuples/products with standard syntax
auto (a,b) = (1,2);
(int a, string b) = fetch!((x)=>(1,text(x)));
[(1,2),(3,4)].map!((a,b)=>a+b).each!writeln;
>> - built-in tagged unions/sums,
Not sure about detailed syntax, maybe something like:
(int+string) x = inj(0,1);
(int+string) y = inj(1,"hi");
> nullable,
Maybe:
int*? x=null;
writeln(*x); // error
if(x) writeln(*x); // ok
C? x = ...;
D? = x?.method();
> algebraic data types
Maybe:
enum Result(T){
Ok(T),
Error(string)
}
>> - pattern matching
auto x = match(r){
Ok(0) => 3;
Ok(x) => x+1;
Error(_): assert(0);
}
int toInt((int+string) x)
match(x){
(0, x): return x;
(1, s): return to!int(s);
}
}
>> - real support for linear/affine typing
auto x = S();
auto y = move(x);
auto z = x; // error: undefined identifier x
auto y = move(y); // ok
// error: y was not explicitly moved away or destroyed
>> - named parameters with support for perfect forwarding and compile-time introspection
void foo(int x=0,int y=0,int z=0;
foo(x: 100, z: 200);
auto apply(alias f,T...)(T args){ return f(args); }
apply!foo(x: 100, z: 200);
>> - built-in duck-typed record types playing nice with named parameters
auto r = (x: 100, z: 200);
foo(r);
>> - type classes / some standard way to add UFCS methods to a type from another module that are then visible in an instantiated template from a third module
import a: S;
import b: rangeFun;
auto ref front(ref S s){ ... }
bool empty(ref S s){ ... }
void popFront(){ ... }
void main(){
S s;
rangeFun(s with(front, empty, popFront));
alias T=S with (front,empty,popFront);
T t=s;
rangeFun(t);
}
>> - uniform syntax for function definition, in particular `int add(int a,int b)=>a+b;` (-preview=shortenedMethods)
int add(int a,int b)=>a+b;
>> - `let Statement in Expression` expression
void main(){
auto z = {
int x=1;
int y=2;
} in x+y;
assert(z==3);
}
>> - `Expression where Statement` expression
> ...
void main(){
auto z = x+y where{
int x=1;
int y=2;
};
assert(z==3);
}
> could you give example what those would be like?
> ...
See above. Unfortunately I only had time to give some contrived examples.
>> - mixin identifiers
> example?
static foreach((name, value);[("x",1),("y",2),("z",3)]){
int mixin(name) = value;
}
writeln(x," ",y," ",z); // 1 2 3
>> - __local, static break and continue
> what would __local do?
> ...
static foreach(i;0..100){
__local alias X=Foo!(T[i]); // local to static foreach, does not clash between iterations
mixin Bar!X;
}
>> (https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md)
Also see the explanation in the DIP.
>> - template literals
> example?
enum sizes = staticMap!((B)!=>B.sizeof,Types);
>> - static opIndex/opSlice
>> - AST introspection
>> - consistent treatment of operators for built-in types, e.g. 1.opBinary!"+"(2) should work.
>> - operator overloading should combine orthogonally with UFCS
>> - better support for subtyping (expose the concept to user-defined types, e.g., Range!(const(T)) could be a subtype of const(Range!T)) and any other features required to support a good container library
>> - async/await (or similar)
>> - yield (or similar)
>> - range literals
> what's that?
auto b = (fun(x) for x in iota(100) if bar(x));
// equivalent to:
// auto b = iota(100).filter!(x=>bar(x)).map!(x=>fun(x));
>> - more lightweight coroutines
>> - ProtoObject
>> - special treatment of qualified types, in particular qualified reference types (e.g. `immutable` classes should allow conversion of references from `immutable` to mutable)
>> - non-deterministic semantics, with as little undefined behavior as possible, in particular for type/function qualifiers
>> - compile-time fixed-point support (e.g., with struct S(T){ T* next; }, fix!S gives a singly linked list).
>> - flow-sensitive typing
> what's that?
class A{ void foo(){ ... } }
class B:A{ void bar(){ ... } }
void foo(A a){
if(a is B){
B b=a; // ok
a.bar(); // ok
}
}
>> - strong variable updates (probably not happening)
> what's that?
int x=2;
x="123";
static assert(is(typeof(x)==string));
auto f=File(x,"r");
static assert(is(typeof(f)==File));
f.close();
static assert(is(typeof(f)==ClosedFile));
>> - non-lexical variable lifetimes (probably not happening)
>> - parametric polymorphism, in particular for type qualifiers (probably not happening)
>> - some amount of dependent types (dreaming now)
>
> you got very nice features, are you making DIPs for those?
>
I started this:
https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md
https://github.com/tgehr/dmd/commits/tuple-syntax
Unfortunately, I was too busy at the time to finish the implementation, and I am not fully satisfied with the proposal. Probably I'd want to add at least static opIndex and static opSlice to it. Another issue is that it slightly expands `alias this` and I am not sure whether that's a direction Walter is willing to invest in at this point.
|