Re: Passing Arguments on in Variadic Functions

2015-09-18 Thread jmh530 via Digitalmars-d-learn

On Friday, 18 September 2015 at 00:55:12 UTC, anonymous wrote:

On Thursday 17 September 2015 23:27, jmh530 wrote:

I think I could figure out how to look through the arguments 
for a bool, but wouldn't that make me give up the default 
value for the bool?


If you don't find a bool, you use the default value.


Ah. True.


Re: Passing Arguments on in Variadic Functions

2015-09-17 Thread jmh530 via Digitalmars-d-learn

On Monday, 14 September 2015 at 20:26:56 UTC, jmh530 wrote:

Thanks to you both. This works perfect.


I noticed that there's some interesting interplay with this 
technique and default arguments.


From below, it is required that you put the ones with default 
arguments last. If there are only two arguments, then it takes 
the second to be the default argument. However, I can't actually 
put just one argument, even though V is variadic and sample is a 
default. That seems strange to me because it makes it seem like 
sample really isn't optional.


Not sure if this is a bug or on purpose. The only way I can 
resolve it is by writing another function that just takes x 
(alternately one that takes x and sample only also works).


Also, it doesn't seem to let me put template constraints on V so 
that I could do something like constrain V to be numeric.


import std.algorithm : sum;
import std.stdio : writeln;

auto test(T, V ...)(T x, V seed, bool sample=true)
{
auto sum_x = sum(x, seed);
if (sample)
return sum_x;
else
return sum_x / 2;
}

void main()
{
int[] x = [10, 5, 15, 20, 30];
writeln(test(x, true));
writeln(test(x, false));
float seed = 1;
writeln(test(x, seed, true));
writeln(test(x, seed, false));
}


Re: Passing Arguments on in Variadic Functions

2015-09-17 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 17 September 2015 at 17:35:18 UTC, jmh530 wrote:
I noticed that there's some interesting interplay with this 
technique and default arguments.


Yeah, it expects the V... to consume the rest of the arguments so 
it doesn't really leave any room for the default arg.


I would actually just make it required or do separate functions 
with it. Optional and variadics don't mix well together.


(You could also loop through and look for a bool argument 
yourself but that is a bit messier.)


Also, it doesn't seem to let me put template constraints on V 
so that I could do something like constrain V to be numeric.


import std.meta;
import std.traits;

if(allSatisfy!(isNumeric, V))

should do it


Re: Passing Arguments on in Variadic Functions

2015-09-17 Thread jmh530 via Digitalmars-d-learn
On Thursday, 17 September 2015 at 18:40:56 UTC, Adam D. Ruppe 
wrote:


I would actually just make it required or do separate functions 
with it. Optional and variadics don't mix well together.


(You could also loop through and look for a bool argument 
yourself but that is a bit messier.)




It's a result of dealing with the sum function. The seed 
parameter will override the type. So for instance one option is 
to do something like

auto test(T)(T x,  bool sample=true, T seed=T.init)
ignoring the complexity of T.init being a nan for some types, it 
would also overrule some of the behavior of sum. For instance, if 
you do sum(x) where x is a dynamic array of floats, then the 
result is a double instead of a float.


I think I could figure out how to look through the arguments for 
a bool, but wouldn't that make me give up the default value for 
the bool?


Maybe it would require, doing one version of the function defined 
like

auto test(T)(T x,  bool sample=true)
and then another like
auto test(T, U ...)(T x,  U y)
I could then try to use static ifs to ensure some of the other 
requirements (like a restriction on length so that it's not 
called if there is only one argument in y). I probably don't even 
need to loop, I can just static if that the first one in y is a 
bool and the second is numeric.


Re: Passing Arguments on in Variadic Functions

2015-09-17 Thread jmh530 via Digitalmars-d-learn
On Thursday, 17 September 2015 at 18:40:56 UTC, Adam D. Ruppe 
wrote:


import std.meta;
import std.traits;

if(allSatisfy!(isNumeric, V))

should do it


Was not aware of allSatisfy. Thanks.



Re: Passing Arguments on in Variadic Functions

2015-09-17 Thread jmh530 via Digitalmars-d-learn

On Thursday, 17 September 2015 at 21:27:31 UTC, jmh530 wrote:




There's probably a way to clean this up better, but this is what 
I was talking about.


import std.algorithm : sum;
import std.stdio : writeln;
import std.traits : isNumeric;

auto test(T)(T x, bool sample=true)
{
auto sum_x = sum(x);
if (sample)
return sum_x;
else
return sum_x / 2;
}

auto test(T, V ...)(T x, V y)
{
static if (y.length)
{
static if (y.length == 2 &&
   is(typeof(y[0]) == bool) &&
   isNumeric!(typeof(y[1])))
{
auto sum_x = sum(x, y[1]);
if (y[0])
return sum_x;
else
return sum_x / 2;
}
}
}

void main()
{
int[] x = [10, 5, 15, 20, 30];
writeln(test(x, true));
writeln(test(x, false));
float seed = 1;
writeln(test(x, true, seed));
writeln(test(x, false, seed));
}


Re: Passing Arguments on in Variadic Functions

2015-09-17 Thread anonymous via Digitalmars-d-learn
On Thursday 17 September 2015 23:27, jmh530 wrote:

> I think I could figure out how to look through the arguments for 
> a bool, but wouldn't that make me give up the default value for 
> the bool?

If you don't find a bool, you use the default value.


Re: Passing Arguments on in Variadic Functions

2015-09-14 Thread anonymous via Digitalmars-d-learn
On Monday 14 September 2015 21:59, jmh530 wrote:

> This approach gives the correct result, but dmd won't deduce the 
> type of the template. So for instance, the second to the last 
> line of the unit test requires explicitly stating the types. I 
> may as well use the alternate version that doesn't use the 
> variadic function (which is simple for this trivial example, but 
> maybe not more generally).

You can use a variadic template instead:


import std.algorithm : sum;

auto test(R, E ...)(R r, E e)
{
return sum(r, e);
}

unittest
{
int[] x = [10, 5, 15, 20, 30];
assert(test(x) == 80);
assert(test(x, 0f) == 80f);
assert(test(x, 0f) == 80f);
}



Re: Passing Arguments on in Variadic Functions

2015-09-14 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 14 September 2015 at 19:59:18 UTC, jmh530 wrote:
In R, it is easy to have some optional inputs labeled as ... 
and then pass all those optional inputs in to another function. 
I was trying to get something similar to work in a templated D 
function, but I couldn't quite get the same behavior. What I 
have below is what I was able to get working.


You want to generally avoid the varargs and instead use variadic 
templates. The syntax is similar but a bit different:


R test(R, E, Args...)(Args args) {
static if(Args.length == 0)
// no additional arguments
else
return sum(args);
}


or whatever you actually need. But what this does is take any 
number of arguments of various types but makes that length and 
type available at compile time for static if inspection.


The args represents the whole list and you can loop over it, 
convert to an array with `[args]` (if they are all compatible 
types, or pass to another function as a group like I did here.


This is the way writeln is implemented btw.


Re: Passing Arguments on in Variadic Functions

2015-09-14 Thread jmh530 via Digitalmars-d-learn

Thanks to you both. This works perfect.


Passing Arguments on in Variadic Functions

2015-09-14 Thread jmh530 via Digitalmars-d-learn
In R, it is easy to have some optional inputs labeled as ... and 
then pass all those optional inputs in to another function. I was 
trying to get something similar to work in a templated D 
function, but I couldn't quite get the same behavior. What I have 
below is what I was able to get working.


This approach gives the correct result, but dmd won't deduce the 
type of the template. So for instance, the second to the last 
line of the unit test requires explicitly stating the types. I 
may as well use the alternate version that doesn't use the 
variadic function (which is simple for this trivial example, but 
maybe not more generally).


Do I have any options to get it more similar to the way R does 
things?


import std.algorithm : sum;
import core.vararg;

auto test(R)(R r)
{
return sum(r);
}

auto test(R, E)(R r, ...)
{
if (_arguments.length == 0)
return test(r);
else
{
auto seed = va_arg!(E)(_argptr);
return sum(r, seed);
}
}

auto test_alt(R, E)(R r, E seed)
{
return sum(r, seed);
}

unittest
{
int[] x = [10, 5, 15, 20, 30];
assert(test(x) == 80);
assert(test!(int[], float)(x, 0f) == 80f);
assert(test_alt(x, 0f) == 80f);
}