Thread overview | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 17, 2013 How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
I can't figure out how to do the following C++ code in D: int arr[] = { 1, 3, 5, 7, 11 }; template <typename... T> void foo(T... values) { } template <typename... T> void bar(T... values) { foo((arr[values] * 10)...); } int main() { bar(1, 3, 4); /* calls foo(arr[1] * 10, arr[3] * 10, arr[4] * 10); */ return 0; } This is how I tried to do it in D, but it doesn't work: import std.conv; import std.typetuple; int[5] arr = [ 1, 3, 5, 7, 11 ]; void foo(T...)(T values) { } void bar(T...)(T values) { foo(expandWrapped!("arr[@] * 10", values)); } template expandWrapped(string fmt, X...) { string compose() { string ret = "alias expandWrapped = TypeTuple!("; foreach (i; 0 .. X.length) { auto iStr = to!string(i); foreach (ch; fmt) { if (ch == '@') { ret ~= "X[" ~ iStr ~ "]"; } else { ret ~= ch; } } if (i != X.length - 1) { ret ~= ","; } } ret ~= ");"; return ret; } mixin(compose()); // [1] } void main() { bar(1, 3, 4); } 1) Error: variable arr cannot be read at compile time |
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT | Although... now that I think about it, this should really be done as a language feature, and not through some inefficient CTFE trick. So, I should really be able to just write this: int[5] arr = [ 1, 3, 5, 7, 11 ]; void foo(T...)(T values) { } void bar(T...)(T values) { foo((arr[values] * 10)...); } void main() { bar(1, 3, 4); } |
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT | On 06/16/2013 11:19 PM, TommiT wrote: > I can't figure out how to do the following C++ code in D: > > int arr[] = { 1, 3, 5, 7, 11 }; > > template <typename... T> > void foo(T... values) { } > > template <typename... T> > void bar(T... values) > { > foo((arr[values] * 10)...); > } > > int main() > { > bar(1, 3, 4); /* calls foo(arr[1] * 10, > arr[3] * 10, > arr[4] * 10); */ > return 0; > } The following does not answer the question of expanding but at least foo() receives [30, 70, 110] :) import std.stdio; import std.algorithm; import std.array; import std.range; int[] arr = [ 1, 3, 5, 7, 11 ]; void foo(T)(T[] values...) { writeln(values); } void bar(T)(T[] values...) { foo(arr .indexed(values) .map!(a => a * 10) .array); } void main() { bar(1, 3, 4); } Ali |
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 17 June 2013 at 07:20:23 UTC, Ali Çehreli wrote:
>
> The following does not answer the question of expanding but at least foo() receives [30, 70, 110] :)
>
> import std.stdio;
> import std.algorithm;
> import std.array;
> import std.range;
>
> int[] arr = [ 1, 3, 5, 7, 11 ];
>
> void foo(T)(T[] values...)
> {
> writeln(values);
> }
>
> void bar(T)(T[] values...)
> {
> foo(arr
> .indexed(values)
> .map!(a => a * 10)
> .array);
> }
>
> void main()
> {
> bar(1, 3, 4);
> }
>
> Ali
Yeah, that would work. I'd hate the overhead though.
|
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT | On 06/17/13 11:32, TommiT wrote:
> On Monday, 17 June 2013 at 07:20:23 UTC, Ali Çehreli wrote:
>>
>> The following does not answer the question of expanding but at least foo() receives [30, 70, 110] :)
>>
>> import std.stdio;
>> import std.algorithm;
>> import std.array;
>> import std.range;
>>
>> int[] arr = [ 1, 3, 5, 7, 11 ];
>>
>> void foo(T)(T[] values...)
>> {
>> writeln(values);
>> }
>>
>> void bar(T)(T[] values...)
>> {
>> foo(arr
>> .indexed(values)
>> .map!(a => a * 10)
>> .array);
>> }
>>
>> void main()
>> {
>> bar(1, 3, 4);
>> }
>>
>> Ali
>
> Yeah, that would work. I'd hate the overhead though.
void bar(T...)(T values) {
T tmp;
foreach (i, ref v; values)
tmp[i] = arr[v]*10;
foo(tmp);
}
artur
|
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | On Monday, 17 June 2013 at 11:15:24 UTC, Artur Skawina wrote:
> On 06/17/13 11:32, TommiT wrote:
>> On Monday, 17 June 2013 at 07:20:23 UTC, Ali Çehreli wrote:
>>>
>>> The following does not answer the question of expanding but at least foo() receives [30, 70, 110] :)
>>>
>>> import std.stdio;
>>> import std.algorithm;
>>> import std.array;
>>> import std.range;
>>>
>>> int[] arr = [ 1, 3, 5, 7, 11 ];
>>>
>>> void foo(T)(T[] values...)
>>> {
>>> writeln(values);
>>> }
>>>
>>> void bar(T)(T[] values...)
>>> {
>>> foo(arr
>>> .indexed(values)
>>> .map!(a => a * 10)
>>> .array);
>>> }
>>>
>>> void main()
>>> {
>>> bar(1, 3, 4);
>>> }
>>>
>>> Ali
>>
>> Yeah, that would work. I'd hate the overhead though.
>
> void bar(T...)(T values) {
> T tmp;
> foreach (i, ref v; values)
> tmp[i] = arr[v]*10;
> foo(tmp);
> }
>
> artur
Cool, I didn't know that you could create multiple variables like that (T tmp).
|
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT | On 06/17/13 13:23, TommiT wrote:
> On Monday, 17 June 2013 at 11:15:24 UTC, Artur Skawina wrote:
>> void bar(T...)(T values) {
>> T tmp;
>> foreach (i, ref v; values)
>> tmp[i] = arr[v]*10;
>> foo(tmp);
>> }
>
> Cool, I didn't know that you could create multiple variables like that (T tmp).
A more correct, but a bit less readable version (the types of 'values' and 'arr' elements do not have to match) would be:
void bar(T...)(T values) {
static if (T.length) {
NTup!(T.length, typeof(arr[T[0].init])) tmp;
foreach (i, ref v; values)
tmp[i] = arr[v]*10;
foo(tmp);
}
else
foo();
}
template NTup(size_t N, T...) {
static if (N>1)
alias NTup = NTup!(N-1, T, T[$-1]);
else
alias NTup = T;
}
artur
|
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | On Monday, 17 June 2013 at 12:21:31 UTC, Artur Skawina wrote:
>
> A more correct, but a bit less readable version (the types of 'values' and 'arr'
> elements do not have to match) would be:
>
> void bar(T...)(T values) {
> static if (T.length) {
> NTup!(T.length, typeof(arr[T[0].init])) tmp;
> foreach (i, ref v; values)
> tmp[i] = arr[v]*10;
> foo(tmp);
> }
> else
> foo();
> }
>
> template NTup(size_t N, T...) {
> static if (N>1)
> alias NTup = NTup!(N-1, T, T[$-1]);
> else
> alias NTup = T;
> }
>
> artur
Argh, that's a lot of boilerplate. Thanks for pointing this out. I didn't notice in your previous example that the expression types had to match with the parameter types. Now I really do think that we need the C++ ellipsis notation (it's just the ellipsis can be omitted when it would be right next to the tuple):
void bar(T...)(T values)
{
foo((arr[values] * 10)...);
}
|
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT | On 06/17/13 14:57, TommiT wrote: > On Monday, 17 June 2013 at 12:21:31 UTC, Artur Skawina wrote: >> >> A more correct, but a bit less readable version (the types of 'values' and 'arr' elements do not have to match) would be: >> >> void bar(T...)(T values) { >> static if (T.length) { >> NTup!(T.length, typeof(arr[T[0].init])) tmp; >> foreach (i, ref v; values) >> tmp[i] = arr[v]*10; >> foo(tmp); >> } >> else >> foo(); >> } >> >> template NTup(size_t N, T...) { >> static if (N>1) >> alias NTup = NTup!(N-1, T, T[$-1]); >> else >> alias NTup = T; >> } > > Argh, that's a lot of boilerplate. Thanks for pointing this out. I didn't notice in your previous example that the expression types had to match with the parameter types. Now I really do think that we need the C++ ellipsis notation (it's just the ellipsis can be omitted when it would be right next to the tuple): > > void bar(T...)(T values) > { > foo((arr[values] * 10)...); > } > Well, the only real difference between these two examples is s/T tmp/NTup!(T.length, typeof(arr[T[0].init])) tmp/ 'NTup' would be a lib thing, and the empty-args case would have to handled (or disallowed) in real code anyway. So it's not /that/ much more boilerplate. Another solution would be to have the following hidden in some lib: struct _ForEach(alias MAP, TS...) { NTup!(TS.length, typeof(MAP(TS[0].init))) tuple; this(TS values) { foreach (i, ref v; values) tuple[i] = MAP(v); } } auto ForEach(alias MAP, TS...)(TS ts) { return _ForEach!(MAP, TS)(ts); } Then 'bar' becomes just: void bar(T...)(T values) { foo(ForEach!(a=>arr[a]*10)(values).tuple); } Yes, this is not as concise as '...' would be. But, with a bit more tuple support in the language, the '.tuple' part wouldn't be necessary, and then it's just foo(ForEach!(a=>arr[a]*10)(values)); vs foo((arr[values] * 10)...); artur |
June 17, 2013 Re: How to expand an expression along with a parameter tuple? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | Artur Skawina:
> Yes, this is not as concise as '...' would be. But, with a bit more tuple support in the language, the '.tuple' part wouldn't be
> necessary,
Implicit things are dangerous in languages.
".tuple" can also be written "[]".
Bye,
bearophile
|
Copyright © 1999-2021 by the D Language Foundation