digitalmars.D.learn - Is std.variant.visit not nogc?
- helxi (28/28) Apr 08 2018 import std.variant, core.stdc.stdio;
- Adam D. Ruppe (50/51) Apr 08 2018 These error messages REALLY need to be fixed.
- Hasen Judy (3/14) Apr 09 2018 IMO, this is one more reason why sum-types should be built into
- Chris Katko (14/17) Apr 09 2018 +1. Any time you have to "create" a fundamental feature in a
- Paul Backus (28/35) Apr 09 2018 I agree in general, but in this case it's actually completely
- helxi (2/10) Apr 09 2018 This isn't boxed by any chance, is it?
- Paul Backus (5/17) Apr 09 2018 Nope! It's just a tagged union, almost exactly the same as what
- aliak (11/15) Apr 10 2018 Awesome!
- Paul Backus (17/27) Apr 10 2018 It's called "type sequence instantiation", and it's documented in
- Steven Schveighoffer (7/26) Apr 10 2018 Ooh! that's really cool.
import std.variant, core.stdc.stdio; Algebraic!(T, string) fib_nth(T)(T n) { return n % 15 ? n % 5 ? n % 3 ? Algebraic!(T, string)(n) : Algebraic!(T, string)("Fizz") : Algebraic!(T, string)("Buzz") : Algebraic!(T, string)("Fizzbuzz"); } void main() nogc { foreach (i; 1 .. 101) { fib_nth(i).visit!( (string s) => printf("%s\n", s.ptr), (int n) => printf("%i\n", n) ); } } Complains source/app.d(18,19): Error: nogc function D main cannot call non- nogc function std.variant.visit!(function (string s) => printf("%s\x0a", cast(immutable(char)*)s), function (int n) => printf("%i\x0a", n)).visit!(VariantN!(16LU, int, string)).visit /usr/bin/dmd failed with exit code 1. If so, is there a way to emulate `visit` in a nogc setting?
Apr 08 2018
On Monday, 9 April 2018 at 03:20:58 UTC, helxi wrote:Is std.variant.visit not nogc?These error messages REALLY need to be fixed. visit, being a template, is nogc or not based on the arguments passed to it as well as its own body, so while the error messages point to visit itself, these are frequently actually caused the predicate your pass. ....well, in this case, it is actually visit itself. phobos/std/variant.d(2464): Error: nogc function std.variant.visitImpl!(true, VariantN!(8u, int, string), function (string s) => printf("%s\x0a", cast(immutable(char)*)s), function (int n) => printf("%i\x0a", n)).visitImpl cannot call non- nogc constructor std.variant.VariantException.this phobos/std/variant.d(2469): Error: nogc function std.variant.visitImpl!(true, VariantN!(8u, int, string), function (string s) => printf("%s\x0a", cast(immutable(char)*)s), function (int n) => printf("%i\x0a", n)).visitImpl cannot call non- nogc function std.variant.VariantN!(8u, int, string).VariantN.peek!int.peek phobos/std/variant.d(2469): Error: nogc function std.variant.visitImpl!(true, VariantN!(8u, int, string), function (string s) => printf("%s\x0a", cast(immutable(char)*)s), function (int n) => printf("%i\x0a", n)).visitImpl cannot call non- nogc function std.variant.VariantN!(8u, int, string).VariantN.peek!string.peek phobos/std/variant.d(2173): Error: template instance `std.variant.visitImpl!(true, VariantN!(8u, int, string), function (string s) => printf("%s\x0a", cast(immutable(char)*)s), function (int n) => printf("%i\x0a", n))` error instantiating Ugh, so unreadable even on this level, but at least the actual information is there: std.variant.VariantException.this is not marked nogc (but it prolly could be) VariantN.peek is not nogc because it calls Object.opEquals... which is broken af, sadly, but can probably be fixed for this case by marking TypeInfo.opEquals nogc. I think the peek one is going to be the harder one to work around since any reimplementation of peek is probably going to still call it... though MAYBE you can use `!is` instead of `!=`... and any reimplementation of visit needs to check types. But if you wanna try to work around it, I would copy the visitImpl and visit functions out of std.variant and do some adjustments, then call your version instead (which will be fairly easy btw since they are already UFCS). FYI: the way I got these error messages was to go into the Phobos source and add nogc to the lowest level template in the instantiation chain. Then just recompile your program - no need to recompile Phobos itself since they are templates. I wish the error messages would just do this for you (simulate nogc at the second-highest level) to keep you from having to edit it yourself just to know what it is.
Apr 08 2018
On Monday, 9 April 2018 at 03:41:17 UTC, Adam D. Ruppe wrote:On Monday, 9 April 2018 at 03:20:58 UTC, helxi wrote: visit, being a template, is nogc or not based on the arguments passed to it as well as its own body, so while the error messages point to visit itself, these are frequently actually caused the predicate your pass. [....] std.variant.VariantException.this is not marked nogc (but it prolly could be) VariantN.peek is not nogc because it calls Object.opEquals... which is broken af, sadly, but can probably be fixed for this case by marking TypeInfo.opEquals nogc.IMO, this is one more reason why sum-types should be built into the language compiler, instead of being implemented in user-space.
Apr 09 2018
On Monday, 9 April 2018 at 07:02:50 UTC, Hasen Judy wrote:IMO, this is one more reason why sum-types should be built into the language compiler, instead of being implemented in user-space.+1. Any time you have to "create" a fundamental feature in a language... from inside the language itself... you're going to have confusing error messages, and a huge uphill battle. Look at Boost. While I salute the effort put into those libraries, trying to "fix C++"... "from inside C++" is a fools errand. The upgraded multidimensional array code looks like this: typedef boost::multi_array<double, 3> array_type; typedef array_type::index index; array_type A(boost::extents[3][4][2]); as opposed to you know, in D: double [3][4][2] A; And the D version has useful error messages, small compile times, and it's still easier to read, reason about, and debug.
Apr 09 2018
On Monday, 9 April 2018 at 07:07:58 UTC, Chris Katko wrote:On Monday, 9 April 2018 at 07:02:50 UTC, Hasen Judy wrote:I agree in general, but in this case it's actually completely doable. In fact, I've done it myself: check out 'sumtype' on code.dlang.org. You can replace 'Algebraic' with 'SumType' and 'visit' with 'match' in helxi's example, and everything Just Works™: import sumtype; import core.stdc.stdio; SumType!(T, string) fib_nth(T)(T n) { return n % 15 ? n % 5 ? n % 3 ? SumType!(T, string)(n) : SumType!(T, string)("Fizz") : SumType!(T, string)("Buzz") : SumType!(T, string)("Fizzbuzz"); } void main() nogc { foreach (i; 1 .. 101) { fib_nth(i).match!( (string s) => printf("%s\n", s.ptr), (int n) => printf("%i\n", n) ); } }IMO, this is one more reason why sum-types should be built into the language compiler, instead of being implemented in user-space.+1. Any time you have to "create" a fundamental feature in a language... from inside the language itself... you're going to have confusing error messages, and a huge uphill battle.
Apr 09 2018
On Monday, 9 April 2018 at 15:59:32 UTC, Paul Backus wrote:On Monday, 9 April 2018 at 07:07:58 UTC, Chris Katko wrote:This isn't boxed by any chance, is it?[...]I agree in general, but in this case it's actually completely doable. In fact, I've done it myself: check out 'sumtype' on code.dlang.org. You can replace 'Algebraic' with 'SumType' and 'visit' with 'match' in helxi's example, and everything Just Works™: [...]
Apr 09 2018
On Tuesday, 10 April 2018 at 00:22:18 UTC, helxi wrote:On Monday, 9 April 2018 at 15:59:32 UTC, Paul Backus wrote:Nope! It's just a tagged union, almost exactly the same as what you'd write by hand in C. You can take a look at the source yourself, if you're curious---it's actually pretty simple: https://github.com/pbackus/sumtype/blob/master/src/sumtype.d#L27On Monday, 9 April 2018 at 07:07:58 UTC, Chris Katko wrote:This isn't boxed by any chance, is it?[...]I agree in general, but in this case it's actually completely doable. In fact, I've done it myself: check out 'sumtype' on code.dlang.org. You can replace 'Algebraic' with 'SumType' and 'visit' with 'match' in helxi's example, and everything Just Works™: [...]
Apr 09 2018
On Tuesday, 10 April 2018 at 03:48:25 UTC, Paul Backus wrote:Nope! It's just a tagged union, almost exactly the same as what you'd write by hand in C. You can take a look at the source yourself, if you're curious---it's actually pretty simple: https://github.com/pbackus/sumtype/blob/master/src/sumtype.d#L27Awesome! this is a neat trick: union { AliasSeq!(T0, T1) values; } Is that usage documented somewhere, or is it somewhere in phobos maybe? Also, can Algebraic be fully replaced with this version then or is there some functionality that would stop it going through?
Apr 10 2018
On Tuesday, 10 April 2018 at 12:34:07 UTC, aliak wrote:Awesome! this is a neat trick: union { AliasSeq!(T0, T1) values; } Is that usage documented somewhere, or is it somewhere in phobos maybe? Also, can Algebraic be fully replaced with this version then or is there some functionality that would stop it going through?It's called "type sequence instantiation", and it's documented in the "Compile-time Sequences" article [1] on dlang.org. I discovered it reading the source of the 'tagged_union' dub package [2]. It's not mentioned anywhere in the language spec, as far as I can tell. SumType should be capable of doing anything that Algebraic can do (if it's not, please open an issue on Github!), but it's not a drop-in replacement, and it's still a work in progress. Documentation for the current version (more or less) is available at http://sumtype.dpldocs.info/index.html. If there are any particular features you'd like to see, let me know, and I'll do my best to add them. [1] https://dlang.org/articles/ctarguments.html#type-seq-instantiation [2] https://github.com/Superstar64/tagged_union/blob/master/source/tagged_union.d
Apr 10 2018
On 4/10/18 12:59 PM, Paul Backus wrote:On Tuesday, 10 April 2018 at 12:34:07 UTC, aliak wrote:Ooh! that's really cool. I've put AliasSeq of types into a struct, but never considered putting it into a union. This has a lot of potential when you want to auto-generate unions. Nice trick! -SteveAwesome! this is a neat trick: union { AliasSeq!(T0, T1) values; } Is that usage documented somewhere, or is it somewhere in phobos maybe? Also, can Algebraic be fully replaced with this version then or is there some functionality that would stop it going through?It's called "type sequence instantiation", and it's documented in the "Compile-time Sequences" article [1] on dlang.org. I discovered it reading the source of the 'tagged_union' dub package [2]. It's not mentioned anywhere in the language spec, as far as I can tell.
Apr 10 2018