www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Type functions with std.algorithm

reply Stefan Koch <uplink.coder googlemail.com> writes:
The code below here works with the current talias_master branch!

alias type = __type;

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

import std.algorithm;

enum type[] types = makeTypeArray(int, uint, long, ulong);
enum size4 = types.filter!((type a) { return a.sizeof == 4; } );
pragma(msg, () {
     type[] result = [];
     foreach(t;size4)
     {
         result ~= t;
     }
     return result;
}().tupleof);
// outputs: tuple((int), (uint))
Oct 10 2020
parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Sunday, 11 October 2020 at 00:46:37 UTC, Stefan Koch wrote:
 The code below here works with the current talias_master branch!

 alias type = __type;

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

 import std.algorithm;

 enum type[] types = makeTypeArray(int, uint, long, ulong);
 enum size4 = types.filter!((type a) { return a.sizeof == 4; } );
 pragma(msg, () {
     type[] result = [];
     foreach(t;size4)
     {
         result ~= t;
     }
     return result;
 }().tupleof);
 // outputs: tuple((int), (uint))
Nice! Is there an issue with `std.array.array`, or you just prefer manually converting the range to an array? Btw, dmd can evaluate ranges at compile-time (e.g. in static foreach), so .tupleof could potentially also do that (convert both ranges and arrays of types to a tuples).
Oct 10 2020
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Sunday, 11 October 2020 at 06:22:26 UTC, Petar Kirov 
[ZombineDev] wrote:
 On Sunday, 11 October 2020 at 00:46:37 UTC, Stefan Koch wrote:
 The code below here works with the current talias_master 
 branch!

 alias type = __type;

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

 import std.algorithm;

 enum type[] types = makeTypeArray(int, uint, long, ulong);
 enum size4 = types.filter!((type a) { return a.sizeof == 4; } 
 );
 pragma(msg, () {
     type[] result = [];
     foreach(t;size4)
     {
         result ~= t;
     }
     return result;
 }().tupleof);
 // outputs: tuple((int), (uint))
Nice! Is there an issue with `std.array.array`, or you just prefer manually converting the range to an array? Btw, dmd can evaluate ranges at compile-time (e.g. in static foreach), so .tupleof could potentially also do that (convert both ranges and arrays of types to a tuples).
Indeed there is an issue with std.array.array. It seems to want to convert __type[] into void[] or something. Which makes some template constraint fail. __type[] to void[] cannot be implemented because strictly speaking the __type[] doesn't hold any data. I think this can be fixed, by pretending there to be data, however than I loose other nice properties such as __type.sizeof == 0; So I will likely need to find a different way.
Oct 11 2020
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Sunday, 11 October 2020 at 10:19:56 UTC, Stefan Koch wrote:
 On Sunday, 11 October 2020 at 06:22:26 UTC, Petar Kirov 
 [ZombineDev] wrote:
 Is there an issue with `std.array.array`, or you just prefer 
 manually converting the range to an array? Btw, dmd can 
 evaluate ranges at compile-time (e.g. in static foreach), so 
 .tupleof could potentially also do that (convert both ranges 
 and arrays of types to a tuples).
Indeed there is an issue with std.array.array. ...
I found out what happens. This is funky, so fasten your seatbelts :) Here is the reproducible case: --- property ref inout(T) front(T)(return scope inout(T)[] a) safe pure nothrow nogc // if (!isAutodecodableString!(T[]) && !is(T[] == void[])) commented out to avoid deps { assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof); return a[0]; } template ElementType(R) { pragma(msg, "R: ", R, ", R.init: ", R.init, ", typeof(R.init.front): ", typeof(R.init.front) ); static if (is(typeof(R.init.front.init) T)) alias ElementType = T; else alias ElementType = void; } pragma(msg, is(ElementType!(__type[]) == void)); pragma(msg, is(ElementType!(int[]) == void)); --- Which prints: R: __type[], R.init: null, typeof(R.init.front): __type true R: int[], R.init: null, typeof(R.init.front): int false That tells us that the front wrapper works correctly. range __type[] correctly returns a __type; so R.init.front is a variable of type __type which makes R.init.front.init be the type __emptyType. the bug is that because __emptyType is a type typeof(__emptyType) returns void, which is consistent with how the language has treated types before type functions (they didn't have a type). So all I have to do is to teach that the type of any type is __type. And then everything will work!
Oct 11 2020
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Sunday, 11 October 2020 at 13:49:20 UTC, Stefan Koch wrote:
 So all I have to do is to teach that the type of any type is 
 __type.

 And then everything will work!
Turns out that is not the case now array fails with: phobos/std/conv.d(4529): Error: constructor std.conv.emplaceRef!(__type, __type, __type).emplaceRef.S.this(ref __type _param_0) is not callable using argument types ((__type)) I believe this is an implicit conversion problem ... Seriously how complicated is phobos ... all you need to do is a foreach loop. What does std.conv.emplaceRef have to do with it? remember the code I want to compile is: --- import std.algorithm; import std.range; enum type[] types = makeTypeArray(int, uint, long, ulong); enum size4 = types.filter!((type a) { return a.sizeof == 4; } ).array; --- and now I worrying about std.conv.emplaceRef ?
Oct 11 2020
next sibling parent Stefan Koch <uplink.coder googlemail.com> writes:
On Sunday, 11 October 2020 at 15:46:19 UTC, Stefan Koch wrote:
 On Sunday, 11 October 2020 at 13:49:20 UTC, Stefan Koch wrote:
 So all I have to do is to teach that the type of any type is 
 __type.

 And then everything will work!
Turns out that is not the case now array fails with: phobos/std/conv.d(4529): Error: constructor std.conv.emplaceRef!(__type, __type, __type).emplaceRef.S.this(ref __type _param_0) is not callable using argument types ((__type)) I believe this is an implicit conversion problem ...
Wow this is so strange ... lvalue to ref conversion works just fine. The code below works ... but what else could be going on here? --- alias type = __type; type ret(type x) { alias y = x; y = passthrough(y); return y; } type passthrough(ref type y) { return y; } pragma(msg, ret(int)); // prints int ---
Oct 11 2020
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 11.10.20 17:46, Stefan Koch wrote:
 On Sunday, 11 October 2020 at 13:49:20 UTC, Stefan Koch wrote:
 So all I have to do is to teach that the type of any type is __type.

 And then everything will work!
Turns out that is not the case now array fails with: phobos/std/conv.d(4529): Error: constructor std.conv.emplaceRef!(__type, __type, __type).emplaceRef.S.this(ref __type _param_0) is not callable using argument types ((__type)) I believe this is an implicit conversion problem ...
Probably the compiler thinks that you are calling the function with an rvalue: --- void foo(ref int){} void main(){ foo(2); } --- test.d(2): Error: function `test.foo(ref int _param_0)` is not callable using argument types `(int)` ---
Oct 11 2020
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Sunday, 11 October 2020 at 16:53:25 UTC, Timon Gehr wrote:
 On 11.10.20 17:46, Stefan Koch wrote:
 On Sunday, 11 October 2020 at 13:49:20 UTC, Stefan Koch wrote:
 So all I have to do is to teach that the type of any type is 
 __type.

 And then everything will work!
Turns out that is not the case now array fails with: phobos/std/conv.d(4529): Error: constructor std.conv.emplaceRef!(__type, __type, __type).emplaceRef.S.this(ref __type _param_0) is not callable using argument types ((__type)) I believe this is an implicit conversion problem ...
Probably the compiler thinks that you are calling the function with an rvalue: --- void foo(ref int){} void main(){ foo(2); } --- test.d(2): Error: function `test.foo(ref int _param_0)` is not callable using argument types `(int)` ---
Thanks for the pointer. I hope to fix this bug soon.
Oct 12 2020