www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - TypeFunction example: filtering types

reply Stefan Koch <uplink.coder googlemail.com> writes:
Hi there,

Atlia just wrote of what he thinks first class type should allow 
him to do:
https://forum.dlang.org/post/uscehdzicfluyjyspocm forum.dlang.org

Luckily he does not actually require first class types for this.
type functions do exactly what he wants.

he wrote:

----
import std.algorithm: filter, equal;

type[] types = [int, uint, long, ulong];
auto size4 = types.filter!(a => a.sizeof == 4);
assert(equal(size4, [int, uint]));
---

that of course won't compile because the assert has to be a 
static assert.
also the array literal of types is currently unsupported.
and for some reason isInputRange fails to instantiate for 
`alias[]`
which means we can't use phobos directly.

So we have to implement phobos filter and phobos equal ourselves.
Similarly `==` is not defined for types right now ... and I don't 
see how it makes sense,
given we have the is expression ... which means we have to pass a 
predicate to equals.
Other than that, his code runs with type functions right now!

---
alias type = alias;

type[] makeTypeArray(type[] types ...)
{
     return types;
}


// has to be written because right now, alias.init is the 
errorType;
// which means that is() and __traits(compiles) may fail if 
alias.init is used.

auto filter(alias pred, E)(E array) if (is(typeof(E.init[0]) == 
alias))
{
     E result;
     size_t len;
     result.length = array.length;
     foreach(e;array)
     {
         if (pred(e))
         {
             result[len++] = e;
         }
     }
     return result[0 .. len];
}

bool equal(alias pred, E)(E array1, E array2) if 
(is(typeof(E.init[0]) == alias))
{
     if (array1.length != array2.length)
         return false;

     immutable len = array1.length;

     foreach(i; 0 .. len)
     {
         if (!pred(array1[i], array2[i]))
         {
             return false;
         }
     }
     return true;
}

enum type[] types = makeTypeArray(int, uint, long, ulong);
pragma(msg, makeTypeArray(int, uint, long, ulong).tupleof);
enum type[] size4 = types.filter!((type a) => a.sizeof == 4);
static assert(equal!((type a, type b) => is(a == b)) (size4, 
makeTypeArray(int, uint)));
pragma(msg, size4); // unsurprisingly prints [(int), (uint)]

---

Cheers,
Stefan
Oct 08 2020
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Thursday, 8 October 2020 at 10:59:23 UTC, Stefan Koch wrote:
 Hi there,

 Atlia just wrote of what he thinks first class type should 
 allow him to do:
 https://forum.dlang.org/post/uscehdzicfluyjyspocm forum.dlang.org

 Luckily he does not actually require first class types for this.
 type functions do exactly what he wants.

 he wrote:

 ----
 import std.algorithm: filter, equal;

 type[] types = [int, uint, long, ulong];
 auto size4 = types.filter!(a => a.sizeof == 4);
 assert(equal(size4, [int, uint]));
Note this code should actually compile with type functions in theory. It's only implementation constraints imposed by the structure of DMD, and straight bugs in the type-function implementation that prevent this from working. right now DMD is not aware that alias is the common type of all types and therefore will be unable to type the array literal. That should be fixed in a couple weeks, similarly alias.init will be amended to be the __emptyType. Which is also a basic type that is not a type, but is not an error. I think after that the using std.algorithm with a type function should actually work.
Oct 08 2020