www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - improving std.array.array

reply "monarch_dodra" <monarchdodra gmail.com> writes:
array is one of my favorite features in Phobos. It is such a 
trivially stupid function, yet so incredibly useful/powerful. 
Just call it on any range, and you get a new raw array of the 
corresponding deferred type. Awesome!

...But I think it has one major drawback: You can't specify the 
type of the array you want. For example, if you have a range of 
ints, and you'd want to duplicate it into a range of doubles, 
well array doesn't allow that.

The problem is that:
1) It could do it no problem.
2) Array just screams to be able to write: "auto doubles = 
array!double(myInts);"

While there are... "ways"... to make it work (map with cast op) 
for example, NOTHING would be as straight forward as array!type, 
and NOTHING would be as efficient either... let alone both at the 
same time. It would allow for a powerful idiom to be even more 
powerful.

The above example is simple, but it could allow more powerful 
usage such as:
auto integralThirds = iota(1,20).map(a => a/3).array!int;
Yowza!

Other perks this allows is duplicating an immutable array into a 
non-mutable array:
"auto myMutableInts = array!int(myImmutableInts)."
or duplicating a mutable array into an imutable one.
"auto myImmutableDoubles = array!(immutable 
double)(myMutableInts)."

As this point, the current implementation does not allow either.

----
Regarding the "string versions", I propose a keeping the current 
scheme, but also give the same control of writing:
char[]  mutableShortString = array!char(someString);
wstring wideString         = array!(immutable wchar)(someString);

----
Proposing this improvement, I of course volunteer for 
implementing testing, writing unittest and pushing all this. I've 
already done most of it, and everything works like a charm ;)
These changes break nothing.

----
I discovered 2 bugs in array:
1) array always chokes at duplicating an immutable input, even 
when the input type should allow the operation. This I (think) 
can fix.
2) array(string) always returns a mutable string, since 
"ForeachType" returns a non-qualified char type. Don't know how 
to fix this :/
Jul 22 2012
next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
I hit some of the problems you described a little while ago. 
Jonathan and I came to the conclusion that the best solution is 
to default to the same element type as the passed range, while 
allowing any type which the element type is convertible to to be 
specified via an extra template parameter, just as you proposed.

I have a half-finished version (sans handling of narrow strings) 
lying around, but won't have time to polish it up for inclusion 
in the next few weeks, so feel free to go ahead.

David
Jul 22 2012
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 22 July 2012 at 13:04:18 UTC, David Nadlinger wrote:
 I hit some of the problems you described a little while ago. 
 Jonathan and I came to the conclusion that the best solution is 
 to default to the same element type as the passed range, while 
 allowing any type which the element type is convertible to to 
 be specified via an extra template parameter, just as you 
 proposed.

 I have a half-finished version (sans handling of narrow 
 strings) lying around, but won't have time to polish it up for 
 inclusion in the next few weeks, so feel free to go ahead.

 David
Yeah, I saw your posts regarding that. I hope I won't hit any problems with my implementation.
 What about

 import std.conv: to;
 auto integralThirds = iota(1,20).map(a => to!int(a/3)).array;

 ?

 It even allows converting to strings, which is something I do 
 very often.
While I won't argue the result is not the same, the intent is not as clear (IMO). Suppose the function I wanted to apply was not anonymous, but "foo": Your approach: auto ints = iota(1,20).map(a => to!int(foo(a))).array; or auto ints = iota(1,20).map(foo).map(a => to!int(a)).array; Which (IMO) really doesn't quite translate the intent as well as: auto ints = iota(1,20).map(foo).array!int; ---- I think the bottom line about array is that it requires trivial simplicity.
Jul 22 2012
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Jul 22, 2012 at 1:46 PM, monarch_dodra <monarchdodra gmail.com> wrote:

 ...But I think it has one major drawback: You can't specify the type of the
 array you want. For example, if you have a range of ints, and you'd want to
 duplicate it into a range of doubles, well array doesn't allow that.
 The above example is simple, but it could allow more powerful usage such as:
 auto integralThirds = iota(1,20).map(a => a/3).array!int;
What about import std.conv: to; auto integralThirds = iota(1,20).map(a => to!int(a/3)).array; ? It even allows converting to strings, which is something I do very often. Philippe
Jul 22 2012