www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using std.algorithm.map: Error: cannot implicitly convert expression

reply "Dfr" <deflexor yandex.ru> writes:
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
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
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
parent reply "Dfr" <deflexor yandex.ru> writes:
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
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
 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
As 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
parent reply "Dfr" <deflexor yandex.ru> writes:
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 type
As 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
parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
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