Jump to page: 1 2 3
Thread overview
Proposal: First class types (at compiletime)
Jul 20, 2023
Commander Zot
Jul 20, 2023
H. S. Teoh
Jul 20, 2023
Commander Zot
Jul 20, 2023
TheGag96
Jul 20, 2023
jmh530
Jul 20, 2023
TheGag96
Jul 20, 2023
jmh530
Jul 20, 2023
TheGag96
Jul 20, 2023
Paul Backus
Jul 21, 2023
Commander Zot
Jul 21, 2023
Stefan Koch
Jul 21, 2023
Commander Zot
Jul 21, 2023
Stefan Koch
Jul 21, 2023
Commander Zot
Jul 21, 2023
Paul Backus
Jul 21, 2023
Commander Zot
Jul 21, 2023
Quirin Schroll
Jul 21, 2023
Quirin Schroll
Jul 21, 2023
Commander Zot
Jul 21, 2023
Commander Zot
Jul 21, 2023
MrJay
Aug 07, 2023
sighoya
Aug 08, 2023
Commander Zot
Aug 08, 2023
sighoya
Aug 10, 2023
Stefan Koch
Aug 10, 2023
Commander Zot
July 20, 2023

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);
}
July 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
July 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:
>> 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

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, ...


July 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 AliasSeqs should have clued us in that we should have been thinking about type functions.

July 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:

>

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]

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)

July 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.

July 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:

>

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.

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?

July 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.

July 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:

>

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.

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.

July 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.

« First   ‹ Prev
1 2 3