Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-26 Thread Chris via Digitalmars-d-learn

On Wednesday, 25 May 2016 at 19:07:32 UTC, Era Scarecrow wrote:

On Wednesday, 25 May 2016 at 13:27:28 UTC, Chris wrote:
Why can the tuple be iterated with foreach, as in my quick 
fix, and indexed with tuple[0..], but is not accepted as a 
range? What are the differences? Is there a way to rangify a 
tuple?


 The tuple is identified/used at compile-time, as such it's a 
compiler primitive and not a range. Foreach in this case will 
unroll the loop regardless how it looks. So...


  test(Args...)(Args args) {
  ...
  foreach (const ref i; items)
itemstrings ~= i.to!string;

  Will become: (const and ref are pointless in this example, 
unless the args are referenced)


  test(int arg1, int arg2, int arg3, int arg4) {
  ...
itemstrings ~= arg1.to!string;
itemstrings ~= arg2.to!string;
itemstrings ~= arg3.to!string;
itemstrings ~= arg4.to!string;


 Trying to use map on it was literally expanding the entire 
input to map.


Ah, I didn't know that it was just unrolled. That makes sense, of 
course.


[snip]


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Era Scarecrow via Digitalmars-d-learn

On Wednesday, 25 May 2016 at 13:27:28 UTC, Chris wrote:
Why can the tuple be iterated with foreach, as in my quick fix, 
and indexed with tuple[0..], but is not accepted as a range? 
What are the differences? Is there a way to rangify a tuple?


 The tuple is identified/used at compile-time, as such it's a 
compiler primitive and not a range. Foreach in this case will 
unroll the loop regardless how it looks. So...


  test(Args...)(Args args) {
  ...
  foreach (const ref i; items)
itemstrings ~= i.to!string;

  Will become: (const and ref are pointless in this example, 
unless the args are referenced)


  test(int arg1, int arg2, int arg3, int arg4) {
  ...
itemstrings ~= arg1.to!string;
itemstrings ~= arg2.to!string;
itemstrings ~= arg3.to!string;
itemstrings ~= arg4.to!string;


 Trying to use map on it was literally expanding the entire input 
to map.


  itemstrings => map!(to!string)(items);

  will become (all as individual items, not an array or range):

  itemstrings => map!(to!string)(arg1, arg2, arg3, arg4);

  You could probably use Array() inside which might work, 
assuming they are all the same type (or does it support a 
multi-type? I don't think so, unless you use Variant).


  There's a good section on Homogeneous vs Variadic behavior. 
Starts on page TDPL pg. 159-164


 If you had the function declared as: test(int[] args...) then 
numbers passed with or without an array would be converted as an 
array. so your calling function would have an array which can be 
used with map, however it loses it's flexible template and 
variable types...


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Chris via Digitalmars-d-learn

On Wednesday, 25 May 2016 at 14:48:14 UTC, ag0aep6g wrote:

On 05/25/2016 04:39 PM, Chris wrote:
I see. Maybe it would be worth adding a wrapper to 
typecons.Tuple or

std.range that helps to rangify tuples.


std.range.only is that wrapper.


Duh! Of course! :-)


I cannot think of any use case
right now. I never needed this and in the example that started 
this
thread, it would keep the function from converting mixed 
tuples (cf. my

example above).


I'm not sure what you're saying here. Should the wrapper 
support tuples with different element types? Can't be a range 
then as a range has just one element type.


I'm saying that for the above example something like 
std.range.only doesn't make sense, because the user might want to 
turn anything into string as in


test(1, 2, "v", 4, 'c');

Mixed type tuples cannot be rangified, of course (and 
std.range.only takes care of that).


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread ag0aep6g via Digitalmars-d-learn

On 05/25/2016 04:39 PM, Chris wrote:

I see. Maybe it would be worth adding a wrapper to typecons.Tuple or
std.range that helps to rangify tuples.


std.range.only is that wrapper.


I cannot think of any use case
right now. I never needed this and in the example that started this
thread, it would keep the function from converting mixed tuples (cf. my
example above).


I'm not sure what you're saying here. Should the wrapper support tuples 
with different element types? Can't be a range then as a range has just 
one element type.


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread ag0aep6g via Digitalmars-d-learn

On 05/25/2016 03:27 PM, Chris wrote:

Why can the tuple be iterated with foreach, as in my quick fix, and
indexed with tuple[0..], but is not accepted as a range? What are the
differences?


popFront doesn't make sense with a tuple (aka expression list). When you 
remove the first element of a tuple, you get another tuple of a 
different type, but popFront can't change the type of the range.


In code:


void main()
{
import std.meta: AliasSeq;
AliasSeq!(int, int, int) tuple = AliasSeq!(1, 2, 3);
tuple.popFront(); /* How would this be implemented? Would have to 
change tuple's type to AliasSeq!(int, int). */

}



Is there a way to rangify a tuple?


std.range.only:


void main()
{
import std.meta: AliasSeq;
import std.range: only;
AliasSeq!(int, int, int) tuple = AliasSeq!(1, 2, 3);
auto range = only(tuple);
range.popFront(); /* ok */
}



Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Chris via Digitalmars-d-learn

On Wednesday, 25 May 2016 at 14:32:11 UTC, ag0aep6g wrote:

On 05/25/2016 03:27 PM, Chris wrote:
Why can the tuple be iterated with foreach, as in my quick 
fix, and
indexed with tuple[0..], but is not accepted as a range? What 
are the

differences?


popFront doesn't make sense with a tuple (aka expression list). 
When you remove the first element of a tuple, you get another 
tuple of a different type, but popFront can't change the type 
of the range.


In code:


void main()
{
import std.meta: AliasSeq;
AliasSeq!(int, int, int) tuple = AliasSeq!(1, 2, 3);
tuple.popFront(); /* How would this be implemented? Would 
have to change tuple's type to AliasSeq!(int, int). */

}



Is there a way to rangify a tuple?


std.range.only:


void main()
{
import std.meta: AliasSeq;
import std.range: only;
AliasSeq!(int, int, int) tuple = AliasSeq!(1, 2, 3);
auto range = only(tuple);
range.popFront(); /* ok */
}



I see. Maybe it would be worth adding a wrapper to typecons.Tuple 
or std.range that helps to rangify tuples. I cannot think of any 
use case right now. I never needed this and in the example that 
started this thread, it would keep the function from converting 
mixed tuples (cf. my example above).


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Chris via Digitalmars-d-learn

On Wednesday, 25 May 2016 at 13:27:28 UTC, Chris wrote:
On Wednesday, 25 May 2016 at 12:08:20 UTC, Steven Schveighoffer 
wrote:

On 5/25/16 6:24 AM, pineapple wrote:
On Tuesday, 24 May 2016 at 20:18:34 UTC, Steven Schveighoffer 
wrote:

Slice assignment from range to array is not supported.

In your example, I'm curious why the efforts to specify the 
type? I

think it would work with just saying auto itemstrings = ...



I still get an error if I use auto instead.


OK, I see the other issue now. map takes a range, whereas you 
are giving it a tuple.


-Steve


Why can the tuple be iterated with foreach, as in my quick fix, 
and indexed with tuple[0..], but is not accepted as a range? 
What are the differences? Is there a way to rangify a tuple?


I should add : a homogeneous tuple, e.g. Tuple!(int, int, int);


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Chris via Digitalmars-d-learn
On Wednesday, 25 May 2016 at 12:08:20 UTC, Steven Schveighoffer 
wrote:

On 5/25/16 6:24 AM, pineapple wrote:
On Tuesday, 24 May 2016 at 20:18:34 UTC, Steven Schveighoffer 
wrote:

Slice assignment from range to array is not supported.

In your example, I'm curious why the efforts to specify the 
type? I

think it would work with just saying auto itemstrings = ...



I still get an error if I use auto instead.


OK, I see the other issue now. map takes a range, whereas you 
are giving it a tuple.


-Steve


Why can the tuple be iterated with foreach, as in my quick fix, 
and indexed with tuple[0..], but is not accepted as a range? What 
are the differences? Is there a way to rangify a tuple?


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/25/16 6:24 AM, pineapple wrote:

On Tuesday, 24 May 2016 at 20:18:34 UTC, Steven Schveighoffer wrote:

Slice assignment from range to array is not supported.

In your example, I'm curious why the efforts to specify the type? I
think it would work with just saying auto itemstrings = ...



I still get an error if I use auto instead.


OK, I see the other issue now. map takes a range, whereas you are giving 
it a tuple.


-Steve


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Chris via Digitalmars-d-learn

On Wednesday, 25 May 2016 at 11:14:26 UTC, FreeSlave wrote:


Works with 'only', 'array' and static array slicing.

import std.algorithm : map;
import std.range : only;
import std.conv : to;
import std.stdio : writeln;
import std.string : join;
import std.array : array;

string test(Args...)(in Args items){
immutable string[items.length] itemstrings = 
map!(to!string)(only(items)).array;

return join(itemstrings[], ", ");
}

unittest{
writeln(test(1, 2, 3, 4));
}


Nice, but I think it doesn't work with varying types.

writeln(test(1, 2, "v", 4, 'c'));


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread Chris via Digitalmars-d-learn

On Wednesday, 25 May 2016 at 10:24:19 UTC, pineapple wrote:
On Tuesday, 24 May 2016 at 20:18:34 UTC, Steven Schveighoffer 
wrote:

Slice assignment from range to array is not supported.

In your example, I'm curious why the efforts to specify the 
type? I think it would work with just saying auto itemstrings 
= ...


-Steve


I still get an error if I use auto instead.


If you really need it, this works:

import std.algorithm : map;
import std.conv : to;
import std.stdio : writeln;
import std.string : join;

string test(Args...)(in Args items)
{
writeln(items.stringof);
string[] itemstrings;
foreach (const ref i; items)
itemstrings ~= i.to!string;
// auto itemstrings = items.map!(a => a.to!string);
  return join(itemstrings, ", ");
}

unittest
{
  writeln(test(1, 2, "v", 4, 'c'));
}

If you use map!(), you get this error:

Error: template map_error.test!(int, int, string, int, 
char).test.map!((a) => a.to!string).map cannot deduce function 
from argument types !()(const(int), const(int), const(string), 
const(int), const(char)), candidates are:

/home/christoph/.dvm/compilers/dmd-2.071.0/linux/bin/../../src/phobos/std/algorithm/iteration.d(450):
map_error.test!(int, int, string, int, char).test.map!((a) => 
a.to!string).map(Range)(Range r) if (isInputRange!(Unqual!Range))

The argument types don't match, i.e. they are const(int) etc. 
instead of int. The arguments are passed as a tuple:


cf. writeln(items.stringof);
tuple(_param_0, _param_1, _param_2, _param_3, _param_4)




Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread FreeSlave via Digitalmars-d-learn

On Tuesday, 24 May 2016 at 20:03:14 UTC, pineapple wrote:
I would've expected this to work, but instead I get a compile 
error. Is my syntax wrong? Is this just not a case that map can 
handle, and I should be doing something else?


import std.algorithm : map;
import std.conv : to;
import std.stdio : writeln;
import std.string : join;

string test(Args...)(in Args items){
immutable string[items.length] itemstrings = 
map!(to!string)(items);

return join(itemstrings, ", ");
}

unittest{
writeln(test(1, 2, 3, 4));
}


Works with 'only', 'array' and static array slicing.

import std.algorithm : map;
import std.range : only;
import std.conv : to;
import std.stdio : writeln;
import std.string : join;
import std.array : array;

string test(Args...)(in Args items){
immutable string[items.length] itemstrings = 
map!(to!string)(only(items)).array;

return join(itemstrings[], ", ");
}

unittest{
writeln(test(1, 2, 3, 4));
}


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-25 Thread pineapple via Digitalmars-d-learn
On Tuesday, 24 May 2016 at 20:18:34 UTC, Steven Schveighoffer 
wrote:

Slice assignment from range to array is not supported.

In your example, I'm curious why the efforts to specify the 
type? I think it would work with just saying auto itemstrings = 
...


-Steve


I still get an error if I use auto instead.


Re: What's wrong with my usage of std.algorithm.map in this code example?

2016-05-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/24/16 4:03 PM, pineapple wrote:

I would've expected this to work, but instead I get a compile error. Is
my syntax wrong? Is this just not a case that map can handle, and I
should be doing something else?

 import std.algorithm : map;
 import std.conv : to;
 import std.stdio : writeln;
 import std.string : join;

 string test(Args...)(in Args items){
 immutable string[items.length] itemstrings =
map!(to!string)(items);


Slice assignment from range to array is not supported.

In your example, I'm curious why the efforts to specify the type? I 
think it would work with just saying auto itemstrings = ...


-Steve


What's wrong with my usage of std.algorithm.map in this code example?

2016-05-24 Thread pineapple via Digitalmars-d-learn
I would've expected this to work, but instead I get a compile 
error. Is my syntax wrong? Is this just not a case that map can 
handle, and I should be doing something else?


import std.algorithm : map;
import std.conv : to;
import std.stdio : writeln;
import std.string : join;

string test(Args...)(in Args items){
immutable string[items.length] itemstrings = 
map!(to!string)(items);

return join(itemstrings, ", ");
}

unittest{
writeln(test(1, 2, 3, 4));
}