www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Map and arrays

reply Tom <tom nospam.com> writes:
Hi,

I wonder how to solve this kind of stuff...

void foo(string[] sarray) {
     // do something with sarray
}

void bar(int[] iarray) {
     auto sarray = map!(to!string)(iarray);
     foo(sarray);
}

And get...

foo (string[] sarray) is not callable using argument types (Map!(to,int[]))

What should I do? Is there some way to get the original array type?

Thanks in advance,
Tom;
Nov 27 2010
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday 27 November 2010 22:48:28 Tom wrote:
 Hi,
 
 I wonder how to solve this kind of stuff...
 
 void foo(string[] sarray) {
      // do something with sarray
 }
 
 void bar(int[] iarray) {
      auto sarray = map!(to!string)(iarray);
      foo(sarray);
 }
 
 And get...
 
 foo (string[] sarray) is not callable using argument types (Map!(to,int[]))
 
 What should I do? Is there some way to get the original array type?

Many functions in std.algorithm return range types specific to that function. A number of these do lazy evaluation, so the actual work of the function is done when iterating over the resulting range. map happens to be one of those. For all such functions, if you want an array out of the deal, what you do is pass the result to std.array.array(). That will take an arbitrary range and return its contents as an array - which also forces the processing of the range in the case of lazy evaluation like you get with map. So, if you want to delay the evaluation at all, or if it's really only go to make sense that some of the range be processed, you may not want to actually put it in an array. The combination of auto and templates can avoid making you actually turn it into an array in many cases. But if you do want an array, std.array.array() is what you're looking for. - Jonathan M Davis
Nov 27 2010
parent reply Tom <tom nospam.com> writes:
El 28/11/2010 04:11, Jonathan M Davis escribió:
 On Saturday 27 November 2010 22:48:28 Tom wrote:
 Hi,

 I wonder how to solve this kind of stuff...

 void foo(string[] sarray) {
       // do something with sarray
 }

 void bar(int[] iarray) {
       auto sarray = map!(to!string)(iarray);
       foo(sarray);
 }

 And get...

 foo (string[] sarray) is not callable using argument types (Map!(to,int[]))

 What should I do? Is there some way to get the original array type?

Many functions in std.algorithm return range types specific to that function. A number of these do lazy evaluation, so the actual work of the function is done when iterating over the resulting range. map happens to be one of those. For all such functions, if you want an array out of the deal, what you do is pass the result to std.array.array(). That will take an arbitrary range and return its contents as an array - which also forces the processing of the range in the case of lazy evaluation like you get with map. So, if you want to delay the evaluation at all, or if it's really only go to make sense that some of the range be processed, you may not want to actually put it in an array. The combination of auto and templates can avoid making you actually turn it into an array in many cases. But if you do want an array, std.array.array() is what you're looking for. - Jonathan M Davis

Thank you very much. Is there some documentation (besides digitalmars ddoc's, which I find very chaotic for a starting point) that explains these structures, when to use them (instead of arrays), and how they interact with arrays? It's very difficult to find that kind of documentation, if there's such. Also I wish to point out that the layout and presentation of some of phobos ddoc pages are, IMHO and as I said before, a little bit of a mess. Wish they could look more like javadoc, or at least more organized. Kind regards. Tom;
Nov 28 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Tom:

 Also I wish to point out that the layout and presentation of some of 
 phobos ddoc pages are, IMHO and as I said before, a little bit of a 
 mess. Wish they could look more like javadoc, or at least more organized.

D docs will surely need improvements, but I don't think they will look like javadoc because Walter follows the typical engineering principle of "brutal simplicity" :-) Bye, bearophile
Nov 28 2010
prev sibling parent reply Tom <tom nospam.com> writes:
El 28/11/2010 20:37, Jonathan M Davis escribió:
 On Sunday 28 November 2010 11:37:26 Tom wrote:
 El 28/11/2010 04:11, Jonathan M Davis escribió:
 On Saturday 27 November 2010 22:48:28 Tom wrote:
 Hi,

 I wonder how to solve this kind of stuff...

 void foo(string[] sarray) {

        // do something with sarray

 }

 void bar(int[] iarray) {

        auto sarray = map!(to!string)(iarray);
        foo(sarray);

 }

 And get...

 foo (string[] sarray) is not callable using argument types
 (Map!(to,int[]))

 What should I do? Is there some way to get the original array type?

Many functions in std.algorithm return range types specific to that function. A number of these do lazy evaluation, so the actual work of the function is done when iterating over the resulting range. map happens to be one of those. For all such functions, if you want an array out of the deal, what you do is pass the result to std.array.array(). That will take an arbitrary range and return its contents as an array - which also forces the processing of the range in the case of lazy evaluation like you get with map. So, if you want to delay the evaluation at all, or if it's really only go to make sense that some of the range be processed, you may not want to actually put it in an array. The combination of auto and templates can avoid making you actually turn it into an array in many cases. But if you do want an array, std.array.array() is what you're looking for. - Jonathan M Davis

Thank you very much. Is there some documentation (besides digitalmars ddoc's, which I find very chaotic for a starting point) that explains these structures, when to use them (instead of arrays), and how they interact with arrays? It's very difficult to find that kind of documentation, if there's such.

Typically the point is _not_ to care about them. You use auto, so you don't care what the type actually is. If you want to pass them to a function, you have it be a templated function. Perhaps it has a template constraint to verify that the range is a particular type of range (such as std.range.isForwardRange!()) rather than a totally arbitrary type, but you're not supposed to have to care that map returns a Map object. Heck, exactly what type of range it is depends on what type of range the one you gave to map was (e.g. if you gave map a random access range - such as an array - than map returns a version of Map which is random access range, whereas if you fed it a range which isn't a random access range, then it isn't a random access range). You're not supposed to have to care. So, to some extent at least, the documentation tries to bury it (which is definitely better than telling you all of its gory details which is more along the lines of what it did in the past). If you want to know what the return type of a function is, use typeof. And if you _really_ want to know what that return type actually looks like, then you need to look at the source code (which would be in dmd2/src/phobos/std/algorithm.d in the after you unzip the dmd zip file). But you're just not supposed to have to care. I'm sure that the documentation could be improved, but it is better than it used to be, and auto removes most of the need to worry about what the exact type a return value is.
 Also I wish to point out that the layout and presentation of some of
 phobos ddoc pages are, IMHO and as I said before, a little bit of a
 mess. Wish they could look more like javadoc, or at least more organized.

It's better than it used to be. I'm sure that it will improve more in the future. But there are higher priorities (like bug fixing), so it's not something that's likely to happen right away - certainly not massive change. I don't expect that it will ever look quite like javadoc does, but it should be getting better eventually. In theory, ddoc output can be made to look like pretty much anything (javadoc included) - and what's up on the site is definitely better than what you get by default - but that means that someone has to do the work to make it look like whatever looks really good (which is one of those things which is highly subjective). It's improving, but slowly. - Jonathan M Davis

I'm not criticizing ddoc color or fonts. I mean, for example, in the index of symbols at the beginning of every ddoc page, there are functions, constants, classes, and templates, all mixed and each next to the other. It doesn't even have an alphabetic ordering. It was difficult to me at first sight to understand where to look for things. Maybe it's not that important as bugfixes, but when new programmers get close to D2 (even old D1 fans, like myself), I'm afraid that more than one could feel some frustration. Tom;
Nov 28 2010
parent Tom <tom nospam.com> writes:
El 29/11/2010 01:58, Jonathan M Davis escribió:
 On Sunday 28 November 2010 19:53:36 Tom wrote:
 I'm not criticizing ddoc color or fonts. I mean, for example, in the
 index of symbols at the beginning of every ddoc page, there are
 functions, constants, classes, and templates, all mixed and each next to
 the other. It doesn't even have an alphabetic ordering. It was difficult
 to me at first sight to understand where to look for things. Maybe it's
 not that important as bugfixes, but when new programmers get close to D2
 (even old D1 fans, like myself), I'm afraid that more than one could
 feel some frustration.

Oh, I agree, as do many others. But someone has to come up with a better way of doing it and be motivated enough to figure out what has to be done with regards to macros and css and whatever else about generating the html files needs to be tweaked. Some folks have done work on it, but no one has presented a better solution yet. And the main devs for dmd, druntime, and Phobos are generally working on code fixes rather than documentation fixes. I'm sure that it'll be improved eventually, but someone has to want to do it, get it done, and get the main devs to approve it. That hasn't happened yet. - Jonathan M Davis

I wish I had time to give it a try :( Maybe in a not so remote future... I really appreciate the effort Walter and Andrei (and others) are doing to lift up the language, though. Changing the subject (more or less), when I was having this little Map annoyance I wondered myself, does D2 have a collection library (mainly supporting Set<T> etc.)? Thanks, Tom;
Nov 28 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Tom:

 What should I do? Is there some way to get the original array type?

This code shows two ways to solve your problem: import std.stdio: writeln; import std.algorithm: map; import std.conv: to; import std.traits: ForeachType; import std.array: array; void foo(Range)(Range srange) if (is(ForeachType!Range == string)) { writeln(srange); } void bar(string[] sarray) { writeln(sarray); } void main() { int[] arr = [1, 2, 3]; auto srange = map!(to!string)(arr); foo(srange); string[] sarr = array(srange); bar(sarr); } They are good for different purposes, but in many cases the foo() version is good. If you want to simplify your code a little you may define a helper template like this: template IsIterableType(Range, T) { enum bool IsIterableType = is(ForeachType!Range == T); } void foo2(Range)(Range srange) if (IsIterableType!(Range, string)) { writeln(srange); } Bye, bearophile
Nov 28 2010
parent Tom <tom nospam.com> writes:
El 28/11/2010 08:19, bearophile escribió:
 Tom:

 What should I do? Is there some way to get the original array type?

This code shows two ways to solve your problem: import std.stdio: writeln; import std.algorithm: map; import std.conv: to; import std.traits: ForeachType; import std.array: array; void foo(Range)(Range srange) if (is(ForeachType!Range == string)) { writeln(srange); } void bar(string[] sarray) { writeln(sarray); } void main() { int[] arr = [1, 2, 3]; auto srange = map!(to!string)(arr); foo(srange); string[] sarr = array(srange); bar(sarr); } They are good for different purposes, but in many cases the foo() version is good. If you want to simplify your code a little you may define a helper template like this: template IsIterableType(Range, T) { enum bool IsIterableType = is(ForeachType!Range == T); } void foo2(Range)(Range srange) if (IsIterableType!(Range, string)) { writeln(srange); } Bye, bearophile

Thank's, I'll take a look... Tom;
Nov 28 2010
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On Sun, 28 Nov 2010 06:19:00 -0500
bearophile <bearophileHUGS lycos.com> wrote:

 Tom:
=20
 What should I do? Is there some way to get the original array type?

void foo(Range)(Range srange) if (is(ForeachType!Range =3D=3D string)) { writeln(srange); } [...] If you want to simplify your code a little you may define a helper templa=

=20
 template IsIterableType(Range, T) {
     enum bool IsIterableType =3D is(ForeachType!Range =3D=3D T);
 }
=20
 void foo2(Range)(Range srange) if (IsIterableType!(Range, string)) {
      writeln(srange);
 }

I was just thinking that all the complication about is() (or un-intuitivene= ss) may be replaced by a proper use of interfaces. Possibly with a simple o= perator like 'isa'. Maybe: void foo2(Range)(Range srange) if (Range isa Iterable(string)) { writeln(srange); } or in this case void foo2(Range!T)(Range!T srange) if (T =3D=3D string && Range isa Iterabl= e) { writeln(srange); } ...which is a bit strange because Range exists precisely to be iterable (so= that "Range isa Iterable" is nearly synonym of "Range isa Range"), so this= may reduce to void foo2(Range!T)(Range!T srange) if (T =3D=3D string) { writeln(srange); } (Sure, we may find better idioms.) After all, isn't the whole point of interfaces to tell that a given type ha= s a given capability? Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Nov 28 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 28 November 2010 11:37:26 Tom wrote:
 El 28/11/2010 04:11, Jonathan M Davis escribi=F3:
 On Saturday 27 November 2010 22:48:28 Tom wrote:
 Hi,
=20
 I wonder how to solve this kind of stuff...
=20
 void foo(string[] sarray) {
=20
       // do something with sarray
=20
 }
=20
 void bar(int[] iarray) {
=20
       auto sarray =3D map!(to!string)(iarray);
       foo(sarray);
=20
 }
=20
 And get...
=20
 foo (string[] sarray) is not callable using argument types
 (Map!(to,int[]))
=20
 What should I do? Is there some way to get the original array type?

Many functions in std.algorithm return range types specific to that function. A number of these do lazy evaluation, so the actual work of the function is done when iterating over the resulting range. map happens to be one of those. =20 For all such functions, if you want an array out of the deal, what you =


 is pass the result to std.array.array(). That will take an arbitrary
 range and return its contents as an array - which also forces the
 processing of the range in the case of lazy evaluation like you get with
 map. So, if you want to delay the evaluation at all, or if it's really
 only go to make sense that some of the range be processed, you may not
 want to actually put it in an array. The combination of auto and
 templates can avoid making you actually turn it into an array in many
 cases. But if you do want an array, std.array.array() is what you're
 looking for.
=20
 - Jonathan M Davis

Thank you very much. =20 Is there some documentation (besides digitalmars ddoc's, which I find very chaotic for a starting point) that explains these structures, when to use them (instead of arrays), and how they interact with arrays? It's very difficult to find that kind of documentation, if there's such.

Typically the point is _not_ to care about them. You use auto, so you don't= care=20 what the type actually is. If you want to pass them to a function, you have= it=20 be a templated function. Perhaps it has a template constraint to verify tha= t the=20 range is a particular type of range (such as std.range.isForwardRange!()) r= ather=20 than a totally arbitrary type, but you're not supposed to have to care that= map=20 returns a Map object. Heck, exactly what type of range it is depends on wha= t=20 type of range the one you gave to map was (e.g. if you gave map a random ac= cess=20 range - such as an array - than map returns a version of Map which is rando= m=20 access range, whereas if you fed it a range which isn't a random access ran= ge,=20 then it isn't a random access range). You're not supposed to have to care. = So,=20 to some extent at least, the documentation tries to bury it (which is defin= itely=20 better than telling you all of its gory details which is more along the lin= es of=20 what it did in the past). If you want to know what the return type of a function is, use typeof. And = if=20 you _really_ want to know what that return type actually looks like, then y= ou=20 need to look at the source code (which would be in=20 dmd2/src/phobos/std/algorithm.d in the after you unzip the dmd zip file). B= ut=20 you're just not supposed to have to care. I'm sure that the documentation c= ould=20 be improved, but it is better than it used to be, and auto removes most of = the=20 need to worry about what the exact type a return value is.
 Also I wish to point out that the layout and presentation of some of
 phobos ddoc pages are, IMHO and as I said before, a little bit of a
 mess. Wish they could look more like javadoc, or at least more organized.

It's better than it used to be. I'm sure that it will improve more in the=20 future. But there are higher priorities (like bug fixing), so it's not some= thing=20 that's likely to happen right away - certainly not massive change. I don't= =20 expect that it will ever look quite like javadoc does, but it should be get= ting=20 better eventually. In theory, ddoc output can be made to look like pretty m= uch=20 anything (javadoc included) - and what's up on the site is definitely bette= r than=20 what you get by default - but that means that someone has to do the work to= make=20 it look like whatever looks really good (which is one of those things which= is=20 highly subjective). It's improving, but slowly. =2D Jonathan M Davis
Nov 28 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 28 November 2010 19:53:36 Tom wrote:
 I'm not criticizing ddoc color or fonts. I mean, for example, in the
 index of symbols at the beginning of every ddoc page, there are
 functions, constants, classes, and templates, all mixed and each next to
 the other. It doesn't even have an alphabetic ordering. It was difficult
 to me at first sight to understand where to look for things. Maybe it's
 not that important as bugfixes, but when new programmers get close to D2
 (even old D1 fans, like myself), I'm afraid that more than one could
 feel some frustration.

Oh, I agree, as do many others. But someone has to come up with a better way of doing it and be motivated enough to figure out what has to be done with regards to macros and css and whatever else about generating the html files needs to be tweaked. Some folks have done work on it, but no one has presented a better solution yet. And the main devs for dmd, druntime, and Phobos are generally working on code fixes rather than documentation fixes. I'm sure that it'll be improved eventually, but someone has to want to do it, get it done, and get the main devs to approve it. That hasn't happened yet. - Jonathan M Davis
Nov 28 2010
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 28 November 2010 21:49:19 Tom wrote:
 El 29/11/2010 01:58, Jonathan M Davis escribi=F3:
 On Sunday 28 November 2010 19:53:36 Tom wrote:
 I'm not criticizing ddoc color or fonts. I mean, for example, in the
 index of symbols at the beginning of every ddoc page, there are
 functions, constants, classes, and templates, all mixed and each next =



 the other. It doesn't even have an alphabetic ordering. It was difficu=



 to me at first sight to understand where to look for things. Maybe it's
 not that important as bugfixes, but when new programmers get close to =



 (even old D1 fans, like myself), I'm afraid that more than one could
 feel some frustration.

Oh, I agree, as do many others. But someone has to come up with a better way of doing it and be motivated enough to figure out what has to be done with regards to macros and css and whatever else about generating the html files needs to be tweaked. Some folks have done work on it, but no one has presented a better solution yet. And the main devs for dmd, druntime, and Phobos are generally working on code fixes rather than documentation fixes. I'm sure that it'll be improved eventually, but someone has to want to do it, get it done, and get the main devs to approve it. That hasn't happened yet. =20 - Jonathan M Davis

I wish I had time to give it a try :( Maybe in a not so remote future... =20 I really appreciate the effort Walter and Andrei (and others) are doing to lift up the language, though. =20 Changing the subject (more or less), when I was having this little Map annoyance I wondered myself, does D2 have a collection library (mainly supporting Set<T> etc.)?

Containers/Collections are in std.container. It is a bit sparse at the mome= nt=20 though. It only has SList (singly-linked list), Array (the equivalent of a = C++=20 vector), and BinaryHeap. A RedBlackTree is in the works and should be inclu= ded=20 soon (which will give you a container which can act like a set), but it has= n't=20 made it in yet. I'm not sure why, since supposedly the implementation is do= ne.=20 Eventually, it should have the full array of containers which it makes sens= e to=20 have in a standard library, but it's one of the newer modules and so is a b= it on=20 the sparse side. =2D Jonathan M Davis
Nov 28 2010