digitalmars.D.learn - Comparing two AliasSeq
- Yuxuan Shui (16/16) Mar 24 2017 In this example:
- H. S. Teoh via Digitalmars-d-learn (9/26) Mar 24 2017 Firstly, is(T : U) expects T and U to be types, and expandRange!(...) is
- Jonathan M Davis via Digitalmars-d-learn (18/34) Mar 24 2017 Well, is expressions normally compare types, not values, and
- Yuxuan Shui (10/53) Mar 24 2017 I see. I always thought tuple() is a type...
- Jonathan M Davis via Digitalmars-d-learn (32/40) Mar 24 2017 An AliasSeq isn't really ever a type. AliasSeq!(int, float) is a list of
- Yuxuan Shui (4/17) Mar 24 2017 Because I want to make use of the "static foreach unrolling"
In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why?
Mar 24 2017
On Sat, Mar 25, 2017 at 03:25:27AM +0000, Yuxuan Shui via Digitalmars-d-learn wrote:In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why?Firstly, is(T : U) expects T and U to be types, and expandRange!(...) is not a type (or a list of types), it is a list of values. Second, is(T : U) means "does the type T implicitly convert to the type U?". It checks for implicit convertibility between types, it does not compare values. T -- The right half of the brain controls the left half of the body. This means that only left-handed people are in their right mind. -- Manoj Srivastava
Mar 24 2017
On Saturday, March 25, 2017 03:25:27 Yuxuan Shui via Digitalmars-d-learn wrote:In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why?Well, is expressions normally compare types, not values, and AliasSeq!(0, 1, 2, 3, 4), isn't a type and doesn't contain types. static assert(is(AliasSeq!int == AliasSeq!int)); passes, whereas static assert(is(AliasSeq!0 == AliasSeq!0)); does not. So, I expect that the issue is that you're dealing with values rather than types. You're also using : instead of ==, and : _definitely_ is for types (since it checks for implicit conversion, not equality), so it wouldn't have entirely surprised me if == worked when : didn't, but == doesn't either. What you proobably should do is either convert the AliasSeq's to dynamic arrays or ranges - e.g. [AliasSeq!(0, 1, 2, 3, 4)] or only(AliasSeq!(0, 1, 2, 3, 4)) - though in both cases, that really only makes sense when you already have an AliasSeq, since [] and only will take the values directly. - Jonathan M Davis
Mar 24 2017
On Saturday, 25 March 2017 at 04:23:31 UTC, Jonathan M Davis wrote:On Saturday, March 25, 2017 03:25:27 Yuxuan Shui via Digitalmars-d-learn wrote:I see. I always thought tuple() is a type... So a tuple of types is a type, but a tuple of mixed types and values is not a type. Doesn't seem very consistent. Here is the solution I will go with: struct test(T...) { } import std.range; static assert (is(test!(expandRange!(iota(0,5))) == test!(0, 1, 2, 3, 4)));In this example: import std.range; template expandRange(alias R) if (isInputRange!(typeof(R))) { static if (R.empty) alias expandRange = AliasSeq!(); else alias expandRange = AliasSeq!(R.front(), expandRange!(R.drop(1))); } /// unittest { import std.range; static assert (is(expandRange!(iota(0,5)): AliasSeq!(0,1,2,3,4))); } The static assert fails, why?Well, is expressions normally compare types, not values, and AliasSeq!(0, 1, 2, 3, 4), isn't a type and doesn't contain types. static assert(is(AliasSeq!int == AliasSeq!int)); passes, whereas static assert(is(AliasSeq!0 == AliasSeq!0)); does not. So, I expect that the issue is that you're dealing with values rather than types. You're also using : instead of ==, and : _definitely_ is for types (since it checks for implicit conversion, not equality), so it wouldn't have entirely surprised me if == worked when : didn't, but == doesn't either. What you proobably should do is either convert the AliasSeq's to dynamic arrays or ranges - e.g. [AliasSeq!(0, 1, 2, 3, 4)] or only(AliasSeq!(0, 1, 2, 3, 4)) - though in both cases, that really only makes sense when you already have an AliasSeq, since [] and only will take the values directly. - Jonathan M Davis
Mar 24 2017
On Saturday, March 25, 2017 04:57:26 Yuxuan Shui via Digitalmars-d-learn wrote:I see. I always thought tuple() is a type... So a tuple of types is a type, but a tuple of mixed types and values is not a type. Doesn't seem very consistent.An AliasSeq isn't really ever a type. AliasSeq!(int, float) is a list of types, not a type itself, and is expressions supports comparing those in at least some instances, because is expressions operate on types, and having them support a list of types is useful. Calling AliasSeq!(int, float) a type would be like claiming that the (int, float) in foo!(int, float) a type. It's a list - a list of template arguments in this case - but it's still a list and not itself a type. An AliaSeq (or tuple as the compiler incorrectly calls it) is essentially a list of symbols or expressions - or aliases - which is why TypeTuple got renamed to AliasSeq; it's not really a tuple (since unlike a tuple, it always expands and is not nestable), and it doesn't hold just types. Also, it's used for template parameters, template arguments, function parameters, and function arguments, so you can't really call it a list of parameters or arguments. So, so it's sort of a list or sequence of aliases, that's what it got changed to - AliasSeq. But that's still not a great name for it. It can just hold too many different things and be used in too many different ways. Essentially though, an AliasSeq is a list of template/function parameters/arguments that happens to be separated from any templates or functions at the moment. In any case, since is expressions are entirely meant for operating on types, having them not work with an AliaSeq that includes values makes sense. In general, mixing types and values in a single AliasSeq isn't a great idea - (though sometimes that's exactly what's required for template arguments). So, code that mixes them is not the norm.Here is the solution I will go with: struct test(T...) { } import std.range; static assert (is(test!(expandRange!(iota(0,5))) == test!(0, 1, 2, 3, 4)));Why are you using is expressons at all? Why are you creating a type? You're dealing purely with values here. As such, why aren't you just using arrays or ranges? At least with your example here, using an AliasSeq is just complicating life. Dynamic arrays and ranges can be used at compile time via CTFE and are a lot more straightforward to use. - Jonathan M Davis
Mar 24 2017
On Saturday, 25 March 2017 at 05:20:44 UTC, Jonathan M Davis wrote:On Saturday, March 25, 2017 04:57:26 Yuxuan Shui via Digitalmars-d-learn wrote:Because I want to make use of the "static foreach unrolling" feature (I don't know what's the official name).[...]An AliasSeq isn't really ever a type. AliasSeq!(int, float) is a list of types, not a type itself, and is expressions supports comparing those in at least some instances, because is expressions operate on types, and having them support a list of types is useful. Calling AliasSeq!(int, float) a type would be like claiming that the (int, float) in foo!(int, float) a type. It's a list - a list of template arguments in this case - but it's still a list and not itself a type. [...][...]
Mar 24 2017