Thread overview
Using std.algorithm.map: Error: cannot implicitly convert expression of type MapResult!
Dec 10, 2013
Dfr
Dec 10, 2013
Philippe Sigaud
Dec 10, 2013
Dfr
Dec 10, 2013
bearophile
Dec 10, 2013
Philippe Sigaud
Dec 11, 2013
Dfr
Dec 11, 2013
Philippe Sigaud
December 10, 2013
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 ?
December 10, 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);
}
December 10, 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);
> }
December 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
December 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 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);
}
December 11, 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 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);
> }

December 11, 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