digitalmars.D - Proposal: First class types (at compiletime)
- Commander Zot (50/50) Jul 20 2023 wouldn't it be possible to have something like first class types
- H. S. Teoh (16/26) Jul 20 2023 [...]
- Commander Zot (21/47) Jul 20 2023 yes, you could write it that way, but the same is true for
- TheGag96 (15/17) Jul 20 2023 Unfortunately, I think that may be the case. Work has actually
- jmh530 (4/15) Jul 20 2023 You mean dropping it was a mistake? Or you mean type functions
- TheGag96 (3/6) Jul 20 2023 Sorry, I was probably unclear - not going the type functions
- jmh530 (7/13) Jul 20 2023 Thanks.
- TheGag96 (3/8) Jul 20 2023 Again, my original comment may have been unclear (argh lol). It
- Paul Backus (9/15) Jul 20 2023 The thing is, none of the existing template stuff is ever going
- Commander Zot (9/25) Jul 21 2023 but without having them, we still have to write recursive
- Stefan Koch (12/39) Jul 21 2023 I can share the latest state of type-functions before I abandoned
- Commander Zot (10/50) Jul 21 2023 thx. but as i understand it, this is quite different then what i
- Stefan Koch (7/18) Jul 21 2023 In order to convert TypeInfo[] into real types you need to build
- Commander Zot (56/76) Jul 21 2023 yes, you need a TypeInfo like type_t in my example.
- Paul Backus (5/10) Jul 21 2023 Following this design philosophy is how you end up with C++.
- Commander Zot (15/26) Jul 21 2023 I'm sorry, but I don't see how you'd have to write any glue code.
- Quirin Schroll (32/35) Jul 21 2023 Of course, that’s possible. You’d have a type called `Type` that
- Quirin Schroll (16/26) Jul 21 2023 Note that, in my understanding of “first-class,” this isn’t
- Commander Zot (14/42) Jul 21 2023 that's why i thought first-class only at compiletime.
- Commander Zot (8/43) Jul 21 2023 we already have TypeInfo, which should be used for this too. i'd
- MrJay (46/49) Jul 21 2023 In some programming languages I have used in the past
- sighoya (26/26) Aug 07 2023 Nice work.
- Commander Zot (12/35) Aug 08 2023 I could imagine rules where this works, as type_t!short would be
- sighoya (8/16) Aug 08 2023 The more I think about your solution, the more I like it. It
- Stefan Koch (3/6) Aug 09 2023 You need the origin so you can compute a mangle.
- Commander Zot (11/18) Aug 10 2023 you need the fully qualified name anyway, or else you run into
wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE? the idea is to make this work ``` type_t min(type_t a, type_t b){ return a.sizeof<=b.sizeof?a:b; } alias r = min(short, int); ``` basically an equivalent to ``` int min(int a, int b){return a<=b?a:b;} enum r = min(2, 4); ``` here's a working example how it's kind of possible in D atm, but lacks the syntax sugar: ``` struct Foo { struct Bar { } } struct type_t { private: size_t _size; string _ts; public: size_t sizeof_() { return _size; } } auto t(T)() { import std.traits : fullyQualifiedName; enum tis = fullyQualifiedName!T; return type_t(T.sizeof, tis); } template r(type_t xt) { mixin("alias r = " ~ xt._ts ~";"); } // use normal functions for type logic instead of template magic (basically a CTFE equivalant for type logic) auto min_type(type_t a, type_t b) { return a.sizeof_ <= b.sizeof_ ? a : b; } void main() { enum XT = t!(Foo.Bar); alias T = r!(XT); pragma(msg, T); alias ST = r!(min_type(t!short, t!int)); pragma(msg, ST); } ```
Jul 20 2023
On Thu, Jul 20, 2023 at 01:44:15PM +0000, Commander Zot via Digitalmars-d wrote:wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE? the idea is to make this work ``` type_t min(type_t a, type_t b){ return a.sizeof<=b.sizeof?a:b; } alias r = min(short, int); ```[...] What are you trying to accomplish that needs to do this? If you describe your use case, maybe we can better understand why you can't just use a simple template: template Min(T, U) { static if (T.sizeof <= U.sizeof) alias Min = T; else alias Min = U; } alias V = Min!(int, short); static assert(is(V == short)); T -- Some ideas are so stupid that only intellectuals could believe them. -- George Orwell
Jul 20 2023
On Thursday, 20 July 2023 at 14:46:49 UTC, H. S. Teoh wrote:On Thu, Jul 20, 2023 at 01:44:15PM +0000, Commander Zot via Digitalmars-d wrote:yes, you could write it that way, but the same is true for value-based calculations. CTFE allows us to write normal functions instead of templates for value logic at compiletime, we're just lacking first class type support to also use them for type logic compiletime. currently we have runtime functions in std.algorithm and the same in std.meta for types for example. it would be nice if we could do ``` import std.algorithm; alias TS = (int, short, byte).filter!(t=>t.sizeof>1).aliasseq; ``` and it wouldn't need too much changes i think (but i might be wrong there): - make type parameters and return types implicitly convert to TypeInfo - make typeinfo/typeid work properly in CTFE - make an asignment to an alias convert a TypeInfo into the corresponding type at compiletime. - add some special functions to TypeInfo, like comparison, sizeof, ...wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE? the idea is to make this work ``` type_t min(type_t a, type_t b){ return a.sizeof<=b.sizeof?a:b; } alias r = min(short, int); ```[...] What are you trying to accomplish that needs to do this? If you describe your use case, maybe we can better understand why you can't just use a simple template: template Min(T, U) { static if (T.sizeof <= U.sizeof) alias Min = T; else alias Min = U; } alias V = Min!(int, short); static assert(is(V == short)); T
Jul 20 2023
On Thursday, 20 July 2023 at 15:11:39 UTC, Commander Zot wrote:and it wouldn't need too much changes i think (but i might be wrong there):Unfortunately, I think that may be the case. Work has actually been done to explore in this in the past by Stefan Koch under the name "type functions": https://forum.dlang.org/post/swuxfggqgibqbxoaiheg forum.dlang.org He had a WIP implementation and everything. However, it wasn't met with much reception from the higher-ups and was more or less dropped, I think. Languages like Jai and Zig it seems have shown this as largely been a mistake... D's compile-time capabilities are super cool, but the C++ carryover of having basically a separate language of sorts by way of templates to operate on types is slow to compile and hokey compared to just... writing a function. Honestly, the point where we started having to do recursion to do list operations on `AliasSeq`s should have clued us in that we should have been thinking about type functions.
Jul 20 2023
On Thursday, 20 July 2023 at 15:46:26 UTC, TheGag96 wrote:On Thursday, 20 July 2023 at 15:11:39 UTC, Commander Zot wrote:You mean dropping it was a mistake? Or you mean type functions are a mistake? (if so, can you explain more what those languages had an issue with)and it wouldn't need too much changes i think (but i might be wrong there):Unfortunately, I think that may be the case. Work has actually been done to explore in this in the past by Stefan Koch under the name "type functions": https://forum.dlang.org/post/swuxfggqgibqbxoaiheg forum.dlang.org He had a WIP implementation and everything. However, it wasn't met with much reception from the higher-ups and was more or less dropped, I think. Languages like Jai and Zig it seems have shown this as largely been a mistake... [snip]
Jul 20 2023
On Thursday, 20 July 2023 at 16:57:16 UTC, jmh530 wrote:You mean dropping it was a mistake? Or you mean type functions are a mistake? (if so, can you explain more what those languages had an issue with)Sorry, I was probably unclear - not going the type functions route was a mistake.
Jul 20 2023
On Thursday, 20 July 2023 at 17:52:38 UTC, TheGag96 wrote:On Thursday, 20 July 2023 at 16:57:16 UTC, jmh530 wrote:Thanks. Stefan's work seemed interesting to me at the time, but it didn't seem like something trivial. I'm not sure I recall in the forums Walter or Atila having a strong opinion, but that could just be my recollection. Maybe something for D3?You mean dropping it was a mistake? Or you mean type functions are a mistake? (if so, can you explain more what those languages had an issue with)Sorry, I was probably unclear - not going the type functions route was a mistake.
Jul 20 2023
On Thursday, 20 July 2023 at 18:55:14 UTC, jmh530 wrote:Stefan's work seemed interesting to me at the time, but it didn't seem like something trivial. I'm not sure I recall in the forums Walter or Atila having a strong opinion, but that could just be my recollection. Maybe something for D3?Again, my original comment may have been unclear (argh lol). It was indeed very non-trivial, which is the unfortunate part.
Jul 20 2023
On Thursday, 20 July 2023 at 17:52:38 UTC, TheGag96 wrote:On Thursday, 20 July 2023 at 16:57:16 UTC, jmh530 wrote:The thing is, none of the existing template stuff is ever going away. So the choice is not really between "templates" and "first-class types", it's between "templates" and "both". I agree that, in retrospect, relying on templates for metaprogramming was probably a mistake. But at this point, there's nothing we can do to fix it short of starting a new language from scratch--which is not something the D leadership has any interest in.You mean dropping it was a mistake? Or you mean type functions are a mistake? (if so, can you explain more what those languages had an issue with)Sorry, I was probably unclear - not going the type functions route was a mistake.
Jul 20 2023
On Thursday, 20 July 2023 at 21:09:40 UTC, Paul Backus wrote:On Thursday, 20 July 2023 at 17:52:38 UTC, TheGag96 wrote:but without having them, we still have to write recursive template metaprogramming for things that would be expressed better with normal functions. yes, it wouldn't remove old code, but it would be a huge win for any new code in my opinion. and I remember walter mention CTFE for calculations as a huge win, so i'm really not sure if this wouldn't be either. which is the point why I bring up the topic.On Thursday, 20 July 2023 at 16:57:16 UTC, jmh530 wrote:The thing is, none of the existing template stuff is ever going away. So the choice is not really between "templates" and "first-class types", it's between "templates" and "both". I agree that, in retrospect, relying on templates for metaprogramming was probably a mistake. But at this point, there's nothing we can do to fix it short of starting a new language from scratch--which is not something the D leadership has any interest in.You mean dropping it was a mistake? Or you mean type functions are a mistake? (if so, can you explain more what those languages had an issue with)Sorry, I was probably unclear - not going the type functions route was a mistake.
Jul 21 2023
On Friday, 21 July 2023 at 11:53:23 UTC, Commander Zot wrote:On Thursday, 20 July 2023 at 21:09:40 UTC, Paul Backus wrote:I can share the latest state of type-functions before I abandoned the approach. I believe this is close to what I ended up wtih: https://github.com/dlang/dmd/compare/master...UplinkCoder:dmd:talias_master as you can see it's quite a bit of code and it leads to strange interactions with the type system. At the time I thought that's inherent and cannot be fixed, and indeed if you want to keep the same syntax that you are used to using in templates, this may very well be the case. However if you are willing to accept changes to your code, it might be possible to do something like this.On Thursday, 20 July 2023 at 17:52:38 UTC, TheGag96 wrote:but without having them, we still have to write recursive template metaprogramming for things that would be expressed better with normal functions. yes, it wouldn't remove old code, but it would be a huge win for any new code in my opinion. and I remember walter mention CTFE for calculations as a huge win, so i'm really not sure if this wouldn't be either. which is the point why I bring up the topic.On Thursday, 20 July 2023 at 16:57:16 UTC, jmh530 wrote:The thing is, none of the existing template stuff is ever going away. So the choice is not really between "templates" and "first-class types", it's between "templates" and "both". I agree that, in retrospect, relying on templates for metaprogramming was probably a mistake. But at this point, there's nothing we can do to fix it short of starting a new language from scratch--which is not something the D leadership has any interest in.You mean dropping it was a mistake? Or you mean type functions are a mistake? (if so, can you explain more what those languages had an issue with)Sorry, I was probably unclear - not going the type functions route was a mistake.
Jul 21 2023
On Friday, 21 July 2023 at 12:14:01 UTC, Stefan Koch wrote:On Friday, 21 July 2023 at 11:53:23 UTC, Commander Zot wrote:thx. but as i understand it, this is quite different then what i proposed, right? my proposal doesn't implement 'type functions' as a special kind of function, it just uses TypeInfo as a parameter and return type. so my idea would be to allow any type to implicitly convert to it's TypeInfo when a type is used in a expression. and any TypeInfo to be converted back to it's type when assigned to an alias. TypeInfo[] should be converted back to an AliasSeq of those types.On Thursday, 20 July 2023 at 21:09:40 UTC, Paul Backus wrote:I can share the latest state of type-functions before I abandoned the approach. I believe this is close to what I ended up wtih: https://github.com/dlang/dmd/compare/master...UplinkCoder:dmd:talias_master as you can see it's quite a bit of code and it leads to strange interactions with the type system. At the time I thought that's inherent and cannot be fixed, and indeed if you want to keep the same syntax that you are used to using in templates, this may very well be the case. However if you are willing to accept changes to your code, it might be possible to do something like this.On Thursday, 20 July 2023 at 17:52:38 UTC, TheGag96 wrote:but without having them, we still have to write recursive template metaprogramming for things that would be expressed better with normal functions. yes, it wouldn't remove old code, but it would be a huge win for any new code in my opinion. and I remember walter mention CTFE for calculations as a huge win, so i'm really not sure if this wouldn't be either. which is the point why I bring up the topic.On Thursday, 20 July 2023 at 16:57:16 UTC, jmh530 wrote:The thing is, none of the existing template stuff is ever going away. So the choice is not really between "templates" and "first-class types", it's between "templates" and "both". I agree that, in retrospect, relying on templates for metaprogramming was probably a mistake. But at this point, there's nothing we can do to fix it short of starting a new language from scratch--which is not something the D leadership has any interest in.You mean dropping it was a mistake? Or you mean type functions are a mistake? (if so, can you explain more what those languages had an issue with)Sorry, I was probably unclear - not going the type functions route was a mistake.
Jul 21 2023
On Friday, 21 July 2023 at 12:42:06 UTC, Commander Zot wrote:thx. but as i understand it, this is quite different then what i proposed, right? my proposal doesn't implement 'type functions' as a special kind of function, it just uses TypeInfo as a parameter and return type. so my idea would be to allow any type to implicitly convert to it's TypeInfo when a type is used in a expression. and any TypeInfo to be converted back to it's type when assigned to an alias. TypeInfo[] should be converted back to an AliasSeq of those types.In order to convert TypeInfo[] into real types you need to build special code into the compiler. The information contained in TypeInfo[] is not by itself enough to create a type. All of the transformation on types or TypeInfo need to be threaded through the compiler.
Jul 21 2023
On Friday, 21 July 2023 at 12:46:12 UTC, Stefan Koch wrote:On Friday, 21 July 2023 at 12:42:06 UTC, Commander Zot wrote:yes, you need a TypeInfo like type_t in my example. for reference here's how my example currently works with TypeInfo[]: ```d struct Foo { struct Bar { } } struct type_t { private: size_t _size; string _ts; public: size_t sizeof_() { return _size; } } auto t(T)() { import std.traits : fullyQualifiedName; enum tis = fullyQualifiedName!T; return type_t(T.sizeof, tis); } template r(type_t xt) { mixin("alias r = " ~ xt._ts ~";"); } template r(type_t[] xts) { import std.algorithm; import std.array; import std.meta; mixin("alias r = AliasSeq!(" ~ xts.map!(t=>t._ts).array.join(",") ~");"); } // use normal functions for type logic instead of template magic (basically a CTFE equivalant for type logic) auto both(type_t a, type_t b) { return [a,b]; } void main() { enum XT = t!(Foo.Bar); alias T = r!(XT); pragma(msg, T); alias ST = r!(both(t!short, t!int)); pragma(msg, ST); } ``` this is already working in current D. it's just annoying that you have to write t! and r! everywhere. the idea is to lower ``` alias T = foo(short, int); ``` into some sort of ``` alias T = type_from_typeid(foo(typeid(short), typeid(int))); ```thx. but as i understand it, this is quite different then what i proposed, right? my proposal doesn't implement 'type functions' as a special kind of function, it just uses TypeInfo as a parameter and return type. so my idea would be to allow any type to implicitly convert to it's TypeInfo when a type is used in a expression. and any TypeInfo to be converted back to it's type when assigned to an alias. TypeInfo[] should be converted back to an AliasSeq of those types.In order to convert TypeInfo[] into real types you need to build special code into the compiler. The information contained in TypeInfo[] is not by itself enough to create a type. All of the transformation on types or TypeInfo need to be threaded through the compiler.
Jul 21 2023
On Friday, 21 July 2023 at 11:53:23 UTC, Commander Zot wrote:but without having them, we still have to write recursive template metaprogramming for things that would be expressed better with normal functions. yes, it wouldn't remove old code, but it would be a huge win for any new code in my opinion.Following this design philosophy is how you end up with C++. What happens if you want to use "old code" and "new code" in the same project? Not only do you have to deal with both approaches, you have to write extra glue code to make them work together.
Jul 21 2023
On Friday, 21 July 2023 at 13:51:55 UTC, Paul Backus wrote:On Friday, 21 July 2023 at 11:53:23 UTC, Commander Zot wrote:I'm sorry, but I don't see how you'd have to write any glue code. in fact, they work together perfectly fine in my example code. but maybe I'm missing something, could you write an example where the two would actually clash? and also: you could say the same thing about CTFE (for value types) vs templates to do metaprogramming, yet no one complains about that, quite the opposite. I'm also not suggesting adding type functions or new types to D, but automatically lowering the use of a type in an expression into typeid(type), and if a TypeInfo is assigned to an alias, turn it into it's type again. as I've demonstrated you can do this per hand with templates in existing D code without any problems (except I couldn't get it to work with the builtin TypeInfo, so I've created type_t instead).but without having them, we still have to write recursive template metaprogramming for things that would be expressed better with normal functions. yes, it wouldn't remove old code, but it would be a huge win for any new code in my opinion.Following this design philosophy is how you end up with C++. What happens if you want to use "old code" and "new code" in the same project? Not only do you have to deal with both approaches, you have to write extra glue code to make them work together.
Jul 21 2023
On Thursday, 20 July 2023 at 13:44:15 UTC, Commander Zot wrote:wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE?Of course, that’s possible. You’d have a type called `Type` that represents types. Of course, `Type` does not actually exist, a function that takes `Type` parameters or returns `Type` cannot end up in the object file. But for CTFE, the compiler can pretend that `Type` is just a type like `Object`. In my imagination, you’d have a transformation from “actual” types (as per D’s grammar) to `Type` objects. For built-in types, object.d could provide predefined variables, like `Int` for `int`: `Int` is an object of type `Type` that represents `int`. It could be a built-in pseudo-template `type!T()` that returns the `Type` for `T` or maybe the transformation can be applied even implicitly; object.d would contain `enum Int = type!int;` and friends. The `Type` objects can be manipulated with regular functions and function templates. At CTFE, `Type` is just a type. To get “actual” types back from a `Type` object at compile time, you need another mechanism, ideally I’d say, use `mixin`. Instead of `int x;` you could `mixin(Int) x;`. D’s templates are expressive enough to implement every function you could use `Type`, so it’s technically redundant, and not everything that can be expressed using templates can (or should) be done by (CTFE-only) functions with `Type`; essentially every non-alias template is an example. On the other hand, in the current state, every algorithm that could be applied to types (like sorting a bunch of types) must be implemented in templates because the value algorithm cannot be used. That I call redundancy. As a rule of thumb, if you want to *manipulate* types like a puppet master, you’d use a `Type` function; if you’re interested in *using* the types, e.g. handling objects that have that type, you’d use good old templates.
Jul 21 2023
On Friday, 21 July 2023 at 08:52:47 UTC, Quirin Schroll wrote:On Thursday, 20 July 2023 at 13:44:15 UTC, Commander Zot wrote:Note that, in my understanding of “first-class,” this isn’t actually first-class types. You still have transformations. `Type` is a first-class type, and `Type` objects are first-class objects – at least in CTFE –, but types (as per D grammar) are not first-class things. If you had first-class types, you could do something like: ```d Type[] sort(Type[] types) { … } auto Integers = sort(int, long, short); Integers[0] little; Integers[1] middle; Integers[2] large; ``` I guess parsing any expression as a type is out of reach and thus first-class types are as well.wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE?Of course, that’s possible. You’d have a type called `Type` that represents types. Of course, `Type` does not actually exist, a function that takes `Type` parameters or returns `Type` cannot end up in the object file. But for CTFE, the compiler can pretend that `Type` is just a type like `Object`. […]
Jul 21 2023
On Friday, 21 July 2023 at 09:03:15 UTC, Quirin Schroll wrote:On Friday, 21 July 2023 at 08:52:47 UTC, Quirin Schroll wrote:that's why i thought first-class only at compiletime. in your example 'auto Integers' would be a runtime variable, and while this could be made to work, i don't think it's that useful. ```d Type[] sort(Type[] types...) { … } alias Integers = sort(int, long, short); Integers[0] little; Integers[1] middle; Integers[2] large; ``` this should work. however. assigning a Type to an alias would have to make it a real type again. assigning a Type[] to an alias should make it an AliasSeq of types.On Thursday, 20 July 2023 at 13:44:15 UTC, Commander Zot wrote:Note that, in my understanding of “first-class,” this isn’t actually first-class types. You still have transformations. `Type` is a first-class type, and `Type` objects are first-class objects – at least in CTFE –, but types (as per D grammar) are not first-class things. If you had first-class types, you could do something like: ```d Type[] sort(Type[] types) { … } auto Integers = sort(int, long, short); Integers[0] little; Integers[1] middle; Integers[2] large; ``` I guess parsing any expression as a type is out of reach and thus first-class types are as well.wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE?Of course, that’s possible. You’d have a type called `Type` that represents types. Of course, `Type` does not actually exist, a function that takes `Type` parameters or returns `Type` cannot end up in the object file. But for CTFE, the compiler can pretend that `Type` is just a type like `Object`. […]
Jul 21 2023
On Friday, 21 July 2023 at 08:52:47 UTC, Quirin Schroll wrote:On Thursday, 20 July 2023 at 13:44:15 UTC, Commander Zot wrote:we already have TypeInfo, which should be used for this too. i'd just add a alias type_t or something.wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE?Of course, that’s possible. You’d have a type called `Type` that represents types. Of course, `Type` does not actually exist, a function that takes `Type` parameters or returns `Type` cannot end up in the object file. But for CTFE, the compiler can pretend that `Type` is just a type like `Object`. In my imagination, you’d have a transformation from “actual” types (as per D’s grammar) to `Type` objects. For built-in types, object.d could provide predefined variables, like `Int` for `int`: `Int` is an object of type `Type` that represents `int`. It could be a built-in pseudo-template `type!T()` that returns the `Type` for `T` or maybe the transformation can be applied even implicitly; object.d would contain `enum Int = type!int;` and friends. The `Type` objects can be manipulated with regular functions and function templates. At CTFE, `Type` is just a type.To get “actual” types back from a `Type` object at compile time, you need another mechanism, ideally I’d say, use `mixin`. Instead of `int x;` you could `mixin(Int) x;`.I don't see how that would be useful. it's like restricting an int parameter to specific values. it can be done in the function body.D’s templates are expressive enough to implement every function you could use `Type`, so it’s technically redundant, and not everything that can be expressed using templates can (or should) be done by (CTFE-only) functions with `Type`; essentially every non-alias template is an example. On the other hand, in the current state, every algorithm that could be applied to types (like sorting a bunch of types) must be implemented in templates because the value algorithm cannot be used. That I call redundancy. As a rule of thumb, if you want to *manipulate* types like a puppet master, you’d use a `Type` function; if you’re interested in *using* the types, e.g. handling objects that have that type, you’d use good old templates.excatly. and i'm really tired of writing recursive functions for those things.
Jul 21 2023
On Thursday, 20 July 2023 at 13:44:15 UTC, Commander Zot wrote:wouldn't it be possible to have something like first class types (at compile time) to replace tamplates for type logic with regular functions executed at CTFE?In some programming languages I have used in the past specifically Lisp when you define a type you can give it a list of predicates to define the type, its mostly the same except slightly fancier in scala and haskell, in D we already have support for predicates they are called contracts, and you can apply type checking using in, out, assert, and invariant, this gets you most of the way there. when you click on references you will also find one mentions theorem proving using contracts, so its been used in that same area before, if you use mixins and anonymous/voldemort types I bet you could create a nicer way of applying these contracts, getting 95% the way there. that last 5 percent would be recursive peano types and verifying coverage etc... which both are still probably possible using structs. https://dlang.org/spec/contracts.html reference I mentioned: https://web.archive.org/web/20080919174640/http://people.cs.uchicago.edu/~robby/contract-reading-list/ I guess the next question is, how far can you take contracts for type level programming, and at that point would first class types be necessary. ``` //basic example auto test(float a) in (a < 255) out(r; r.x > 0) { Struct S { float x; float y; float z; invariant { assert(x < 255 && x > -60); assert(y < 255 && y > -60); assert(z < 255 && z > -60); } } S ret = S(a, 100.0, 100.0); return ret; } ``` I did not check if the code compiled but that is the basic idea, there are also examples on the docs I linked, hopefully this gave you some more stuff you can try out / research, and this is also something I am interested in so I would like to see updates if you come up with anything.
Jul 21 2023
Nice work. It seems you want to lower types to values representing types. The problem is that types in single init a declaration. I think grammar alone could not solve the idea of type as expression and type as declaration on it's own: ```D int i,short* s; ``` So is short* s an expression type_t!short * type_t!s or a declaration? The former is useless but there probably trickier examples I don't know. Further you still need to write: ```D type_t min(type_t t1,type_t t2)(){...} ``` otherwise it would be a runtime function which can't do the alias seq magic. Maybe adding syntactic sugar for it could alleviate: ```D type_t min!(type_t t1,type_t t2){...} ``` but I think it is ambiguous too. Maybe it would be better to pass strings instead of types and retrieve type with its properties out of the string via reflection/traits?
Aug 07 2023
On Monday, 7 August 2023 at 23:06:56 UTC, sighoya wrote:I think grammar alone could not solve the idea of type as expression and type as declaration on it's own: ```D int i,short* s; ``` So is short* s an expression type_t!short * type_t!s or a declaration? The former is useless but there probably trickier examples I don't know.I could imagine rules where this works, as type_t!short would be known at compiletime, so it could be converted to a type. But I agree, there might be cases where it doesn't work. I don't have enough knowledge of the D compiler to evaluate or implement my Idea.Further you still need to write: ```D type_t min(type_t t1,type_t t2)(){...} ``` otherwise it would be a runtime function which can't do the alias seq magic.the point of my idea is for it to be a runtime function. only that in some cases it can be run in CTFE and the result can be converted back to a type as we are in compiletime.Maybe adding syntactic sugar for it could alleviate: ```D type_t min!(type_t t1,type_t t2){...} ``` but I think it is ambiguous too. Maybe it would be better to pass strings instead of types and retrieve type with its properties out of the string via reflection/traits?that's basically special type functions again, which just complicate the language, and I don't see much benefit over templates.
Aug 08 2023
On Tuesday, 8 August 2023 at 09:27:46 UTC, Commander Zot wrote:I could imagine rules where this works, as type_t!short would be known at compiletime, so it could be converted to a type. But I agree, there might be cases where it doesn't work. I don't have enough knowledge of the D compiler to evaluate or implement my Idea.that's basically special type functions again, which just complicate the language, and I don't see much benefit over templates.The more I think about your solution, the more I like it. It would really easy complex type calculations using normal functions, and it's not a change to the type system, just sugar on top of templates. If we could eliminate ambiguities, I would be definitely for it. Though we may need to know more about a type than just the name and the size.
Aug 08 2023
On Tuesday, 8 August 2023 at 12:26:06 UTC, sighoya wrote:If we could eliminate ambiguities, I would be definitely for it. Though we may need to know more about a type than just the name and the size.You need the origin so you can compute a mangle. f(t1, t2) needs to yield mangle_of(f) ~ mangle(t1) ~ mangle(t2)
Aug 09 2023
On Thursday, 10 August 2023 at 04:13:57 UTC, Stefan Koch wrote:On Tuesday, 8 August 2023 at 12:26:06 UTC, sighoya wrote:you need the fully qualified name anyway, or else you run into ambiguities when turning it back into an alias. but i don't understand why you'd need the mangle. your function signature should look like this, so the mangle shouldn't be anything special: ``` struct type_t { string fullyqualifiednameoftype; size_t sizeoftype; } type_t fun(type_t, type_t); ```If we could eliminate ambiguities, I would be definitely for it. Though we may need to know more about a type than just the name and the size.You need the origin so you can compute a mangle. f(t1, t2) needs to yield mangle_of(f) ~ mangle(t1) ~ mangle(t2)
Aug 10 2023