Re: parameter pack to inputRange

2016-05-08 Thread Erik Smith via Digitalmars-d-learn

On Sunday, 8 May 2016 at 23:49:40 UTC, Ali Çehreli wrote:

On 05/08/2016 04:48 PM, Erik Smith wrote:

On Sunday, 8 May 2016 at 22:37:44 UTC, Dicebot wrote:

On Sunday, 8 May 2016 at 14:11:31 UTC, Ali Çehreli wrote:

E front() {
final switch (index) {
/* static */ foreach (i, arg; Args) {
case i:
return arg;
}
}
}


AFAIK, this will do funny things with referencing stack if 
arguments

are variables and not literals.


Thanks! The static array version works for me too.   It would 
be good to
understand more about what is going on.  It looks like the 
cost of the
static array is an extra copy for each element. Maybe there is 
still a

way to avoid that.



I had to change one line of your test code. Dicebot's code work 
with it:


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;
}

static void foo(Args...)(Args args) {
import std.container.array;
auto array = Array!int(toInputRange(args));  // <-- HERE

foreach(a; array) {
import std.stdio : writeln;
writeln("e: ", a);
}
}

void main ( )
{
import std.stdio;
writeln(toInputRange(1, 2, 3));

foo(1,2,3);
}

It used to be

toInputRange!(args)

Ali


I did notice that but forgot to mention it - thanks for 
clarifying.  Again it definitely works but it would be nice to 
find a non-copy solution.  I tried to form a static array of 
pointers to the args (see below).  It compiled but the output was 
bad.  I would expect that taking the address of the arguments 
should be safe as long as you are in the called function.



auto toInputRange (T...) (T args) @nogc {
import std.traits : CommonType;
alias E = CommonType!T;

struct Range {
alias P = E*;
P[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] = 
return range;
}




Re: parameter pack to inputRange

2016-05-08 Thread Erik Smith via Digitalmars-d-learn

On Sunday, 8 May 2016 at 22:37:44 UTC, Dicebot wrote:

On Sunday, 8 May 2016 at 14:11:31 UTC, Ali Çehreli wrote:

E front() {
final switch (index) {
/* static */ foreach (i, arg; Args) {
case i:
return arg;
}
}
}


AFAIK, this will do funny things with referencing stack if 
arguments are variables and not literals.


Thanks! The static array version works for me too.   It would be 
good to understand more about what is going on.  It looks like 
the cost of the static array is an extra copy for each element.  
Maybe there is still a way to avoid that.




Re: parameter pack to inputRange

2016-05-08 Thread Erik Smith via Digitalmars-d-learn

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





Re: parameter pack to inputRange

2016-05-06 Thread Erik Smith via Digitalmars-d-learn

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



parameter pack to inputRange

2016-05-05 Thread Erik Smith via Digitalmars-d-learn
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));
}



Re: template auto instantiation when parameters empty

2016-05-05 Thread Erik Smith via Digitalmars-d-learn
On Thursday, 5 May 2016 at 16:12:40 UTC, Steven Schveighoffer 
wrote:

On 5/5/16 12:10 AM, Erik Smith wrote:
I want to have a struct template auto instantiate when the 
template

parameters are defaulted or missing.  Example:

struct Resource(T=int) {
 static auto create() {return Resource(null);}
 this(string s) {}
}

auto resource = Resource.create;

As a plain struct it works, but not as a template:

struct Resource {   // works
struct Resource() {  // fails
struct Resource(T=int) {  // fails

At the call site, this works, but I'm hoping for a few less 
symbols:


auto resource = Resource!().create;

Any ideas?


Instead of static method, use an external factory method:

static auto createResource(T = int)()
{
   return Resource!T(null);
}

And I wouldn't bother with making Resource's T have a default, 
as you'd still have to instantiate it with Resource!() to get 
the default.


-Steve


Alias works at the cost of adding a 2nd type name:

alias Res = Resource!();
auto res  = Res.create

The other problem is that the alias definition by itself 
instantiates, which I can't afford.


I have createResource() now, it just doesn't fit well with the 
rest of the calling styles.


There is also this approach, which might be slightly more 
idiomatic


struct Resource(T) {}
struct Policy {}

auto create(alias T)() {
T!Policy r;
return r;
}

auto r = create!Resource;







template auto instantiation when parameters empty

2016-05-04 Thread Erik Smith via Digitalmars-d-learn
I want to have a struct template auto instantiate when the 
template parameters are defaulted or missing.  Example:


struct Resource(T=int) {
static auto create() {return Resource(null);}
this(string s) {}
}

auto resource = Resource.create;

As a plain struct it works, but not as a template:

struct Resource {   // works
struct Resource() {  // fails
struct Resource(T=int) {  // fails

At the call site, this works, but I'm hoping for a few less 
symbols:


auto resource = Resource!().create;

Any ideas?



Re: what is equivalent to template template

2016-05-03 Thread Erik Smith via Digitalmars-d-learn

You're close.

An `alias` template parameter can be any symbol, including a 
template. But you can't pass in a template as a runtime 
parameter, so having `F f` in your parameters list is wrong 
(there's nothing to pass anyway; you already have the template, 
which is F).


static void call(alias F, A...)(A a) {
F(a);
}

Then instantiate and call the `call` function with the template 
you want:


call!myVariadict(1,2,3);



Works. Thanks!



Re: constructed variadic call

2016-05-03 Thread Erik Smith via Digitalmars-d-learn
I don't think it's possible to call a vararg function whose 
number of arguments is only known at runtime, for the same 
reasons it is impossible in C [1].


Your switch statement is probably the best you can do, other 
than rewriting the API to not use varargs (which, depending on 
what the function is doing, I would recommend). You can 
possibly use string mixins or static foreach to avoid repeating 
the case clauses.


[1] Populating a va_list: 
http://stackoverflow.com/questions/988290/populating-a-va-list


That was fast :).  The generation idea helps a little - thanks.  
It works though and I can't use va_list in this case.


erik




what is equivalent to template template

2016-05-03 Thread Erik Smith via Digitalmars-d-learn
C++ has template templates.  I'm not sure how to achieve the same 
effect where (in example below) the template function myVariadic 
is passed to another function.


void myVaridatic(A...)(A a) {}

static void call(alias F,A...)(F f,A a) {
f(a);
}

void foo() {
call(myVaridatic,1,2,3);
}


Re: constructed variadic call

2016-05-03 Thread Erik Smith via Digitalmars-d-learn

On Monday, 2 May 2016 at 18:56:59 UTC, Stefan Koch wrote:

On Monday, 2 May 2016 at 18:22:52 UTC, Erik Smith wrote:
Is there way to construct an "argument pack" from a non-static 
array (like the switch below)?  I need to transport a variadic 
call through a void*.


switch (a.length) {
  case 1: foo(a[1]); break;
  case 2: foo(a[1], a[2]); break;
  case 3: foo(a[1], a[2], a[3]); break;
...
}


Yes there is.
Using a string mixin.


I'm not sure how to apply mixins here because they require 
compile time evaluation and a.length is runtime.  Ideas?


erik


constructed variadic call

2016-05-02 Thread Erik Smith via Digitalmars-d-learn
Is there way to construct an "argument pack" from a non-static 
array (like the switch below)?  I need to transport a variadic 
call through a void*.


switch (a.length) {
  case 1: foo(a[1]); break;
  case 2: foo(a[1], a[2]); break;
  case 3: foo(a[1], a[2], a[3]); break;
...
}



Re: inferred size for static array initialization

2016-05-02 Thread Erik Smith via Digitalmars-d-learn
I tried to combine the two solutions (Basile with the wrapper, 
Marco with the struct initializer support) but it didn't work. 
The struct initializer is not a array literal (seems obvious 
now).   I might go with the 2nd but it's pretty heavy just to get 
the size.


Thanks.


struct S {
int a, b;
}

auto toStaticArray(alias array)()
{
struct S { int a, b; }

immutable tab = {
static enum S[] s = array;
return cast(typeof(s[0])[s.length])s;
}();
return tab;
}

enum a = toStaticArray!([{1,2},{3,4}]);  // error



inferred size for static array initialization

2016-05-02 Thread Erik Smith via Digitalmars-d-learn
Is there a way to initialize a static array and have it's size 
inferred (and that works for arrays of structs using braced 
literals)?  This would make it easier to maintain longer static 
array definitions.  The code below doesn't work when removing the 
array size even though the array is declared as static immutable.


import std.traits;
static immutable int[] a  = [1,2,3];
static assert(isStaticArray!(typeof(a)));  // fails