Thread overview | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 06, 2016 parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Is there an existing way to adapt a parameter pack to an input range? I would like to construct an array with it. Example: void run(A...) (A args) { Array!int a(toInputRange(args)); } |
May 05, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik Smith | On 05/05/2016 10:00 PM, Erik Smith wrote:
> Is there an existing way to adapt a parameter pack to an input range? I
> would like to construct an array with it. Example:
>
> void run(A...) (A args) {
> Array!int a(toInputRange(args));
> }
>
Just initialize an array with the arguments:
void run(A...) (A args) {
writeln([args]);
}
Ali
|
May 05, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik Smith | On 05/05/2016 10:00 PM, Erik Smith wrote: > Is there an existing way to adapt a parameter pack to an input range? I > would like to construct an array with it. Example: > > void run(A...) (A args) { > Array!int a(toInputRange(args)); > } > Inspired by my DConf 2016 talk ;) here is a fiber-based InputRange solution: import std.stdio; import std.concurrency; import std.container; alias GeneratorFiber = std.concurrency.Generator; void run(A...) (A args) { void asInputRange() { /* static */ foreach (arg; args) { yield(arg); } } auto range = new GeneratorFiber!int(&asInputRange); auto a = Array!int(range); writeln(a[]); } void main() { run(1, 2, 3); } Ali |
May 06, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Friday, 6 May 2016 at 05:20:50 UTC, Ali Çehreli wrote:
> On 05/05/2016 10:00 PM, Erik Smith wrote:
>> Is there an existing way to adapt a parameter pack to an input range? I
>> would like to construct an array with it. Example:
>>
>> void run(A...) (A args) {
>> Array!int a(toInputRange(args));
>> }
>>
>
> Just initialize an array with the arguments:
>
> void run(A...) (A args) {
> writeln([args]);
> }
>
> Ali
That's allocating a dynamic array though, right? It seems like there should be a non-GC adaptor for this purpose (especially since I'm using std.container.array).
erik
|
May 06, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik Smith | Unless parameter list is very (very!) long, I'd suggest to simply copy it into a stack struct. Something like this: auto toInputRange (T...) (T args) { struct Range { T args; size_t index; T[0] front () { return args[index]; } void popFront () { ++index; } bool empty () { return index >= args.length; } } return Range(args, 0); } |
May 06, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Friday, 6 May 2016 at 06:08:24 UTC, Dicebot wrote:
> Unless parameter list is very (very!) long, I'd suggest to simply copy it into a stack struct. Something like this:
>
> auto toInputRange (T...) (T args)
> {
> struct Range
> {
> T args;
> size_t index;
>
> T[0] front () { return args[index]; }
> void popFront () { ++index; }
> bool empty () { return index >= args.length; }
> }
>
> return Range(args, 0);
> }
(note that you can actually make it random access range and not just input range, I simply have not defined required methods)
|
May 06, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik Smith | On Friday, 6 May 2016 at 05:00:48 UTC, Erik Smith wrote: > Is there an existing way to adapt a parameter pack to an input range? I would like to construct an array with it. Example: > > void run(A...) (A args) { > Array!int a(toInputRange(args)); > } Use std.range.only: http://dlang.org/phobos/std_range.html#only void run(A...)(A args) { auto rng = only(args); // ... } |
May 08, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On 05/05/2016 11:08 PM, Dicebot wrote: > Unless parameter list is very (very!) long, I'd suggest to simply copy > it into a stack struct. Something like this: > > auto toInputRange (T...) (T args) > { > struct Range > { > T args; > size_t index; > > T[0] front () { return args[index]; } > void popFront () { ++index; } > bool empty () { return index >= args.length; } > } > > return Range(args, 0); > } I wanted this syntax to work but when I tested I saw that T does not expand to struct members. I like Alex Parrill's only() solution but it allocates a dynamic array as well by doing the equivalent of [args] in the guts of its implementation. As Dicebot said, unless there are tons of arguments, I think the following is the best as it is @nogc. It executes a switch statement for each front() call though. And I like the CommonType!T idea there. import std.stdio; import std.string; /* Support empty Args? */ @nogc pure nothrow auto toInputRange(Args...)() { struct Range { size_t index; bool empty() { return index >= Args.length; } void popFront() { ++index; } import std.traits : CommonType; alias E = CommonType!Args; E front() { final switch (index) { /* static */ foreach (i, arg; Args) { case i: return arg; } } } } return Range(); } unittest { import std.traits; import std.range; static assert(isInputRange!(ReturnType!(toInputRange!(1)))); } void main() { auto r = toInputRange!(1, 2.5, 3); writeln(r); } Ali |
May 08, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 8 May 2016 at 14:11:31 UTC, Ali Çehreli wrote: > On 05/05/2016 11:08 PM, Dicebot wrote: > > Unless parameter list is very (very!) long, I'd suggest to > simply copy > > it into a stack struct. Something like this: > > > > auto toInputRange (T...) (T args) > > { > > struct Range > > { > > T args; > > size_t index; > > > > T[0] front () { return args[index]; } > > void popFront () { ++index; } > > bool empty () { return index >= args.length; } > > } > > > > return Range(args, 0); > > } > > I wanted this syntax to work but when I tested I saw that T does not expand to struct members. > > I like Alex Parrill's only() solution but it allocates a dynamic array as well by doing the equivalent of [args] in the guts of its implementation. > > As Dicebot said, unless there are tons of arguments, I think the following is the best as it is @nogc. It executes a switch statement for each front() call though. And I like the CommonType!T idea there. > > import std.stdio; > import std.string; > > /* Support empty Args? */ > @nogc pure nothrow > auto toInputRange(Args...)() { > struct Range { > size_t index; > > bool empty() { > return index >= Args.length; > } > > void popFront() { > ++index; > } > > import std.traits : CommonType; > alias E = CommonType!Args; > > E front() { > final switch (index) { > /* static */ foreach (i, arg; Args) { > case i: > return arg; > } > } > } > } > > return Range(); > } > > unittest { > import std.traits; > import std.range; > > static assert(isInputRange!(ReturnType!(toInputRange!(1)))); > } > > void main() { > auto r = toInputRange!(1, 2.5, 3); > writeln(r); > } > > Ali I like this solution and it's exactly what I was looking for. However, I'm having an issue when I try to apply it with an actual variadic function. This seems like a DMD bug. static void foo(Args...)(Args args) { import std.container.array; auto array = Array!int(toInputRange!(args)); foreach(a; array) { writeln("e: ", a); } } foo(1,2,3); e:1431827808 e:32767 e:1254116144 |
May 08, 2016 Re: parameter pack to inputRange | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 8 May 2016 at 14:11:31 UTC, Ali Çehreli wrote:
> On 05/05/2016 11:08 PM, Dicebot wrote:
> > Unless parameter list is very (very!) long, I'd suggest to
> simply copy
> > it into a stack struct. Something like this:
> >
> > auto toInputRange (T...) (T args)
> > {
> > struct Range
> > {
> > T args;
> > size_t index;
> >
> > T[0] front () { return args[index]; }
> > void popFront () { ++index; }
> > bool empty () { return index >= args.length; }
> > }
> >
> > return Range(args, 0);
> > }
>
> I wanted this syntax to work but when I tested I saw that T
It does (and it must). I have just tested it and noticed another issue though, one I have not foreseen initially. When accessing variadic variable list, one must use compile-time known index because variables are not guaranteed to be of same size. It can be fixed by using static array (and CommonType is a right call of course):
auto toInputRange (T...) (T args) @nogc
{
import std.traits : CommonType;
alias E = CommonType!T;
struct Range
{
E[T.length] args;
size_t index;
E front () { return args[index]; }
void popFront () { ++index; }
bool empty () { return index >= args.length; }
}
Range range;
foreach (i, ref arg; args)
range.args[i] = arg;
return range;
}
void main ( )
{
import std.stdio;
writeln(toInputRange(1, 2, 3));
}
This version is checked to work on my machine.
|
Copyright © 1999-2021 by the D Language Foundation