www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - RT/CT Type

reply Alex <AJ gmail.com> writes:
Since D has a highly evolved meta programming and it should have 
unitifed type that works two ways:

1. At CT, the type acts as an type or sorta like an alias.
2. At RT the type acts as a string.

Type t = int;

At compile time,

t x;

is the same at

int x;


At RT t = "int"


Why is this important?


The purpose is to unify certain CT and RT code. Because CTFE acts 
as runtime we might use it to build a type, but as a string, such 
as

return getType(T)(T x)
{
     return T.stringof; // CTFE/RT
     //return T // would be simpler
}

But then we could do

getType(32) x;

at CT.

or use getType at runtime.

This is a contrived example but I'm finding that I'm having to 
use CTFE to deal with types which requires strings and then 
convert those strings back in to types using string mixins, which 
is a PIBA.
Apr 02
next sibling parent Dennis <dkorpel gmail.com> writes:
Interesting idea. I heard Stefan Koch was working on a DIP for 
first class types in D, you might be interested in that. I also 
know Zig has a 'comptime' keyword and first class types to do 
meta programming, which removes the explicit distinction between 
RT/CT parameter lists that D has.

On Tuesday, 2 April 2019 at 07:48:23 UTC, Alex wrote:
 This is a contrived example but I'm finding that I'm having to 
 use CTFE to deal with types which requires strings and then 
 convert those strings back in to types using string mixins, 
 which is a PIBA.
Can you give your actual usecase? Your example is already doable with typeof().
Apr 02
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2019-04-02 09:48, Alex wrote:
 Since D has a highly evolved meta programming and it should have 
 unitifed type that works two ways:
 
 1. At CT, the type acts as an type or sorta like an alias.
 2. At RT the type acts as a string.
 
 Type t = int;
 
 At compile time,
 
 t x;
 
 is the same at
 
 int x;
 
 
 At RT t = "int"
 
 
 Why is this important?
 
 
 The purpose is to unify certain CT and RT code. Because CTFE acts as 
 runtime we might use it to build a type, but as a string, such as
 
 return getType(T)(T x)
 {
      return T.stringof; // CTFE/RT
      //return T // would be simpler
 }
 
 But then we could do
 
 getType(32) x;
 
 at CT.
 
 or use getType at runtime.
 
 This is a contrived example but I'm finding that I'm having to use CTFE 
 to deal with types which requires strings and then convert those strings 
 back in to types using string mixins, which is a PIBA.
I would much rather that D had first class types. That is, it would be possible to store types in variables and in arrays and so on. -- /Jacob Carlborg
Apr 02
next sibling parent reply Alex <AJ gmail.com> writes:
On Tuesday, 2 April 2019 at 10:45:37 UTC, Jacob Carlborg wrote:
 On 2019-04-02 09:48, Alex wrote:
 Since D has a highly evolved meta programming and it should 
 have unitifed type that works two ways:
 
 1. At CT, the type acts as an type or sorta like an alias.
 2. At RT the type acts as a string.
 
 Type t = int;
 
 At compile time,
 
 t x;
 
 is the same at
 
 int x;
 
 
 At RT t = "int"
 
 
 Why is this important?
 
 
 The purpose is to unify certain CT and RT code. Because CTFE 
 acts as runtime we might use it to build a type, but as a 
 string, such as
 
 return getType(T)(T x)
 {
      return T.stringof; // CTFE/RT
      //return T // would be simpler
 }
 
 But then we could do
 
 getType(32) x;
 
 at CT.
 
 or use getType at runtime.
 
 This is a contrived example but I'm finding that I'm having to 
 use CTFE to deal with types which requires strings and then 
 convert those strings back in to types using string mixins, 
 which is a PIBA.
I would much rather that D had first class types. That is, it would be possible to store types in variables and in arrays and so on.
Sure, but that isn't likely to happen and probably will be far more work. By simply having them convert to strings in RT helps a lot. When combined with CTFE and mixins it works well because one can go back and forth between type and strings.
Apr 02
parent Paul Backus <snarwin gmail.com> writes:
On 4/2/19 8:38 AM, Alex wrote:
 Sure, but that isn't likely to happen and probably will be far more
 work. By simply having them convert to strings in RT helps a lot. When
 combined with CTFE and mixins it works well because one can go back and
 forth between type and strings.
You cannot, in the general case, go back and forth freely between types and strings using `mixin`. Converting a type to a string discards all of its context information, and there is no way to recover that information from the string alone. Example: https://run.dlang.io/is/EAzKUC Even if this particular issue were fixed (getType could return a fully-qualified name), there would still be the issue of Voldemort types, which can *never* be mixed-in, even with a fully-qualified name.
Apr 02
prev sibling parent reply pham <home home.com> writes:
On Tuesday, 2 April 2019 at 10:45:37 UTC, Jacob Carlborg wrote:
 On 2019-04-02 09:48, Alex wrote:
 Since D has a highly evolved meta programming and it should 
 have unitifed type that works two ways:
 
 
 This is a contrived example but I'm finding that I'm having to 
 use CTFE to deal with types which requires strings and then 
 convert those strings back in to types using string mixins, 
 which is a PIBA.
I would much rather that D had first class types. That is, it would be possible to store types in variables and in arrays and so on.
Delphi has implemented class type for a long time. D should have vision to implement it. However, D also needs to implement inherited constructor in order for it to work Skeleton sample in Delphi type A = class create() virtual // constructor writeln('A.create') B = class(A) create() override // constructor //inherited create() // call inherited constructor implement if needed writeln('B.create') ClassType = class of A; // Any class inherited from A can be used to set to this type ClassType x = A; var x1 = x.create() // output 'A.create' x = B x1 = x.create() // output 'B.create' Cheers Pham
Apr 02
next sibling parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Tuesday, 2 April 2019 at 17:00:41 UTC, pham wrote:
 On Tuesday, 2 April 2019 at 10:45:37 UTC, Jacob Carlborg wrote:
 I would much rather that D had first class types. That is, it 
 would be possible to store types in variables and in arrays 
 and so on.
Delphi has implemented class type for a long time. D should have vision to implement it. However, D also needs to implement inherited constructor in order for it to work Skeleton sample in Delphi type A = class create() virtual // constructor writeln('A.create') B = class(A) create() override // constructor //inherited create() // call inherited constructor implement if needed writeln('B.create') ClassType = class of A; // Any class inherited from A can be used to set to this type ClassType x = A; var x1 = x.create() // output 'A.create' x = B x1 = x.create() // output 'B.create' Cheers Pham
Jacob is talking about "first class" types. D does support classes just like Delphi does (https://dlang.org/spec/class.html): ---- If no call to constructors via this or super appear in a constructor, and the base class has a constructor, a call to super() is inserted at the beginning of the constructor. If there is no constructor for a class, but there is a constructor for the base class, a default constructor is implicitly generated with the form: this() { } ----
Apr 02
prev sibling parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Tuesday, 2 April 2019 at 17:00:41 UTC, pham wrote:
[...]
 Skeleton sample in Delphi

 type
 A = class
   create() virtual  // constructor
     writeln('A.create')

 B = class(A)
   create() override // constructor
     //inherited create() // call inherited constructor 
 implement if needed
     writeln('B.create')

 ClassType = class of A; // Any class inherited from A can be 
 used to set to this type


 ClassType x = A;
 var x1 = x.create()  // output 'A.create'
 x = B
 x1 = x.create()  // output 'B.create'
So in Delphi you can skip calling the constructor of the base class if you omit `inherited create()`? That would be rather odd. D does the right thing: --- import std.stdio; class A { this() { writeln(__FUNCTION__); } } class B : A { this() { writeln(__FUNCTION__); } } void main() { A a = new A; // Output A.this a = new B; // Output A.this, B.this. } --- https://run.dlang.io/is/6b2T4D Bastiaan.
Apr 02