digitalmars.D.learn - Using std.algorithm.map: Error: cannot implicitly convert expression
- Dfr (14/14) Dec 09 2013 Hello, here is example code, which doesn't work:
- Philippe Sigaud (19/26) Dec 09 2013 map, and with it most other algorithm and ranges in std.algorithm and
- Dfr (16/50) Dec 10 2013 Thank you for good explanation.
- bearophile (9/10) Dec 10 2013 The short template instantiation syntax only supports a single
- Philippe Sigaud (25/35) Dec 10 2013 As bearophile said, to!Variant[string]... is read as
- Dfr (9/57) Dec 10 2013 Thank you, this clears thing to me.
- Philippe Sigaud (41/47) Dec 10 2013 For JSON, since the range of types is quite limited, different
Hello, here is example code, which doesn't work: Variant[] vtypes = [ Variant("hello"), Variant("bye") ]; string[] filetypes = map!(to!string)(vtypes); Gives me error: Error: cannot implicitly convert expression (map(vtypes)) of type MapResult!(to, VariantN!(24u)[]) to string[] .... And alternative version: Variant[] vtypes = [ Variant("hello"), Variant("bye") ]; string[] ftypes = map!(t => t.get!(string))(vtypes); Error: cannot implicitly convert expression (map(vtypes)) of type MapResult!(__lambda2, VariantN!(24u)[]) to string[] .... What is wrong here and how to fix it ?
Dec 09 2013
On Tue, Dec 10, 2013 at 6:54 AM, Dfr <deflexor yandex.ru> wrote:Hello, here is example code, which doesn't work: Variant[] vtypes = [ Variant("hello"), Variant("bye") ]; string[] filetypes = map!(to!string)(vtypes); Gives me error: Error: cannot implicitly convert expression (map(vtypes)) of type MapResult!(to, VariantN!(24u)[]) to string[]What is wrong here and how to fix it ?map, and with it most other algorithm and ranges in std.algorithm and std.range, returns lazy ranges: structs that will produce the data you want when you iterate on them (with foreach, for example). What map!(to!string)(someArray) does is constructing a 'view' on someArray that will get you someArray elements, concerted into string. If you want to convert it into an array, use std.array.array: import std.stdio; import std.algorithm; import std.range; import std.array; import std.conv; import std.variant; void main() { Variant[] vtypes = [ Variant("hello"), Variant("bye"), Variant(3.1415) ]; string[] filetypes = map!(to!string)(vtypes).array(); writeln(filetypes); }
Dec 09 2013
Thank you for good explanation. But i currently hit little more complex case and again stuck, maybe some ideas how to resolve this, unfortunately compiler messages not very explanatory. void main() { Variant[] lols = [ Variant(["hello": Variant(1)]), Variant(["bye": Variant(true)]) ]; auto vtypes = map!(to!Variant[string])(lols); // <--- line 11 string[] filetypes = map!(to!string)(vtypes).array(); writeln(filetypes); } Gives me: main.d(11) Error: to!(VariantN!(24u)) is used as a type On Tuesday, 10 December 2013 at 06:05:50 UTC, Philippe Sigaud wrote:On Tue, Dec 10, 2013 at 6:54 AM, Dfr <deflexor yandex.ru> wrote:Hello, here is example code, which doesn't work: Variant[] vtypes = [ Variant("hello"), Variant("bye") ]; string[] filetypes = map!(to!string)(vtypes); Gives me error: Error: cannot implicitly convert expression (map(vtypes)) of type MapResult!(to, VariantN!(24u)[]) to string[]What is wrong here and how to fix it ?map, and with it most other algorithm and ranges in std.algorithm and std.range, returns lazy ranges: structs that will produce the data you want when you iterate on them (with foreach, for example). What map!(to!string)(someArray) does is constructing a 'view' on someArray that will get you someArray elements, concerted into string. If you want to convert it into an array, use std.array.array: import std.stdio; import std.algorithm; import std.range; import std.array; import std.conv; import std.variant; void main() { Variant[] vtypes = [ Variant("hello"), Variant("bye"), Variant(3.1415) ]; string[] filetypes = map!(to!string)(vtypes).array(); writeln(filetypes); }
Dec 10 2013
Dfr:auto vtypes = map!(to!Variant[string])(lols);The short template instantiation syntax only supports a single token, to avoid mistakes,so you need to add (): map!(to!(Variant[string]))(lols); That is better written: lols.map!(to!(Variant[string])); But I don't know if this is enough to fix your code. Bye, bearophile
Dec 10 2013
void main() { Variant[] lols = [ Variant(["hello": Variant(1)]), Variant(["bye": Variant(true)]) ]; auto vtypes = map!(to!Variant[string])(lols); // <--- line 11 string[] filetypes = map!(to!string)(vtypes).array(); writeln(filetypes); } Gives me: main.d(11) Error: to!(VariantN!(24u)) is used as a typeAs bearophile said, to!Variant[string]... is read as to!(Variant)[string], which is not what you want. When a template argument is more than one token long (Variant[string] has 4 tokens), enclose it in parenthesis. But here it will not help you, as I think the conversion you ask is impossible: how could a Variant be transformed into a Variant[string]? By definition of Variant, the compiler cannot know what is inside. The first element of lol could be an a float wrapped into a Variant, for example, and then how could it be transformed into Variant[string]? Do you really need to enclose everything in Variants? Types are your friends, you know :) An array of Variant[string] would be far easier to work with: import std.stdio; import std.algorithm; import std.range; import std.array; import std.conv; import std.variant; void main() { // See the type of lols Variant[string][] lols = [ ["hello": Variant(1)], ["bye": Variant(true)] ]; string[] filetypes = map!(to!string)(lols).array(); writeln(filetypes); }
Dec 10 2013
Thank you, this clears thing to me. I currently has all stuff wrapped in Variants because it is structure parsed from xml (or json), and it could be for example map of Something[string], where Something could be string or array or another map, and also this all nested few levels deep. I'm new to D and maybe there is better solution exists how to represent such structure ? On Tuesday, 10 December 2013 at 18:40:48 UTC, Philippe Sigaud wrote:void main() { Variant[] lols = [ Variant(["hello": Variant(1)]), Variant(["bye": Variant(true)]) ]; auto vtypes = map!(to!Variant[string])(lols); // <--- line 11 string[] filetypes = map!(to!string)(vtypes).array(); writeln(filetypes); } Gives me: main.d(11) Error: to!(VariantN!(24u)) is used as a typeAs bearophile said, to!Variant[string]... is read as to!(Variant)[string], which is not what you want. When a template argument is more than one token long (Variant[string] has 4 tokens), enclose it in parenthesis. But here it will not help you, as I think the conversion you ask is impossible: how could a Variant be transformed into a Variant[string]? By definition of Variant, the compiler cannot know what is inside. The first element of lol could be an a float wrapped into a Variant, for example, and then how could it be transformed into Variant[string]? Do you really need to enclose everything in Variants? Types are your friends, you know :) An array of Variant[string] would be far easier to work with: import std.stdio; import std.algorithm; import std.range; import std.array; import std.conv; import std.variant; void main() { // See the type of lols Variant[string][] lols = [ ["hello": Variant(1)], ["bye": Variant(true)] ]; string[] filetypes = map!(to!string)(lols).array(); writeln(filetypes); }
Dec 10 2013
On Wed, Dec 11, 2013 at 7:26 AM, Dfr <deflexor yandex.ru> wrote:Thank you, this clears thing to me. I currently has all stuff wrapped in Variants because it is structure parsed from xml (or json), and it could be for example map of Something[string], where Something could be string or array or another map, and also this all nested few levels deep. I'm new to D and maybe there is better solution exists how to represent such structure ?For JSON, since the range of types is quite limited, different solutions exists, that depend on what kind of code you prefer: - Having a JSONNode type (a struct, or a class) with a 'type' field (say, a string), that would store whether it's a JSON string, an array of other JSON elements, or a map of JSON elements. Since the range of JSON types is limited, you could have an external enum (enum JSONType {String, Array, Map, ... }) and have you JSONNode contain a member of this kind. External code could then check this field to act accordingly. - Having a hierarchy of class, with a root JSONNode (abstract, I suppose) class, and other, derived classes (JSONArray, JSONMap, ...). A JSONArray would contain an array of JSONNode's, and so on. - Having a bunch of templated structs that would hold together by template constraints, but I don't have the space here to explain it. It's much more complicated and the only advantage I see is being able to construct a value at compile-time. - Using std.variant.Algebraic instead of std.variant.Variant is also an option. For XML, that depends whether you have a DTD, a Schema or whatever, something that limits the kind of XML files you'll receive. - If not, then use a simple node struct, with a name (the XML node name) and an array of nodes as children. It'll give you a generic tree, that is quite OK to represent XML. classes or structs are OK and are mainly a matter of taste here (other might chime in this thread and have other arguments, I'm more a struct guy myself). You'd have to think about how to correclty represent attributes. That also depend of your end goal: just learning to read and manipulate this kind of data in D? Or create a new XML value and write it somewhere? Validation of content (when reading) or allowing the construction only of valid values (when creating) are also interesting subjects. - If you have a DTD and it's fixed, then you can follow the JSON approach: a hierarchy of XML nodes, each containing what's required by the DTD. - If you know you have a DTD but do not know it in advance, then it's still possible, but not in a forum post :) You would have to first parse the DTD, determine what kind of XML node is authorized and then create the required D code. Just know it's perfectly feasible, though more advanced than the other solutions. Cheers, Philippe
Dec 10 2013