Re: Map one tuple to another Tuple of different type

2014-07-22 Thread Vlad Levenfeld via Digitalmars-d-learn
I'm just confused about how static while is supposed to work 
because static foreach, to my understanding, would have to work 
by making a new type for each iteration. I say this because, 1) 
runtime foreach works like that (with type = range), and 2) 
without ctfe foreach, the only way I know of to iterate a 
typelist is to make a new type with one less element, so I 
imagine static foreach lowers to that.


I suppose its possible to make a struct with static immutable 
start and end iterators, and make new types out of advancing the 
start iterator until it was equal to the end. Seems like a step 
backward though.


Anyway my actual question is: if all values are constant at 
compile time, how would a static while loop terminate?


Re: Map one tuple to another Tuple of different type

2014-07-22 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jul 22, 2014 at 03:52:14PM +, Vlad Levenfeld via 
Digitalmars-d-learn wrote:
 I'm just confused about how static while is supposed to work because
 static foreach, to my understanding, would have to work by making a
 new type for each iteration. I say this because, 1) runtime foreach
 works like that (with type = range), and 2) without ctfe foreach, the
 only way I know of to iterate a typelist is to make a new type with
 one less element, so I imagine static foreach lowers to that.
 
 I suppose its possible to make a struct with static immutable start
 and end iterators, and make new types out of advancing the start
 iterator until it was equal to the end. Seems like a step backward
 though.
 
 Anyway my actual question is: if all values are constant at compile
 time, how would a static while loop terminate?

Basically, think of it as custom loop unrolling:

TypeTuple!(
int, x,
float, y,
uint, z
) t;

// This loop:
foreach (i; staticIota(0, 3)) {
t[i]++;
}

// Is equivalent to:
t[0]++;
t[1]++;
t[2]++;

// Which is equivalent to:
t.x++;
t.y++;
t.z++;

The loop body is basically expanded for each iteration, with the loop
variable suitably substituted with each element of the typelist.


T

-- 
Microsoft is to operating systems  security ... what McDonalds is to gourmet 
cooking.


Re: Map one tuple to another Tuple of different type

2014-07-22 Thread via Digitalmars-d-learn
On Tuesday, 22 July 2014 at 16:42:14 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
On Tue, Jul 22, 2014 at 03:52:14PM +, Vlad Levenfeld via 
Digitalmars-d-learn wrote:
Anyway my actual question is: if all values are constant at 
compile

time, how would a static while loop terminate?


Basically, think of it as custom loop unrolling:

TypeTuple!(
int, x,
float, y,
uint, z
) t;

// This loop:
foreach (i; staticIota(0, 3)) {
t[i]++;
}

// Is equivalent to:
t[0]++;
t[1]++;
t[2]++;

// Which is equivalent to:
t.x++;
t.y++;
t.z++;

The loop body is basically expanded for each iteration, with 
the loop

variable suitably substituted with each element of the typelist.


You're misunderstanding him. Your example is a static foreach, 
but Vlad asked about static while. I too don't see how a static 
while is supposed to work.


Re: Map one tuple to another Tuple of different type

2014-07-22 Thread Vlad Levenfeld via Digitalmars-d-learn

Yes, though the loop unrolling is news to me. I'll have to keep
that in mind next time I'm trying to squeeze some extra
performance out of a loop.

btw, found a static switch enhancement request here:
https://issues.dlang.org/show_bug.cgi?id=6921


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread Vlad Levenfeld via Digitalmars-d-learn
Thats real weird that it would reject your i variable, given 
that T.length is known at compile time. I think this is a bug. I 
can get your code to compile if I change your foreach loop to 
this:


foreach(i, U; T)
   modTuple[i] = transTupleElem(argTuple[i]); // ok


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread Vlad Levenfeld via Digitalmars-d-learn

On Monday, 21 July 2014 at 01:29:40 UTC, Daniel Gibson wrote:

Am 21.07.2014 03:05, schrieb Vlad Levenfeld:
Thats real weird that it would reject your i variable, given 
that
T.length is known at compile time. I think this is a bug. I 
can get your

code to compile if I change your foreach loop to this:

foreach(i, U; T)
   modTuple[i] = transTupleElem(argTuple[i]); // ok


That works indeeed.

I also tried foreach(int i, x; argTuple) which also with the 
same error as foreach(i ; 0 .. T.length).


As a workaround I created a TupleIndices template, that would 
return a tuple with 0 .. len and did foreach(i; 
TupleIndices!(T.length) but that was kinda messy and reminded 
me of the loops I had to jump through in C++ to do anything 
useful with variadic templates..


I agree that this is a bug, but at least your workaround is 
much nicer, thanks a lot! :-)


Cheers,
Daniel

(@Vlad: Originally I answered you directly because the 
Thunderbird developers thought it was a clever idea to put an 
answer button that answers to the author instead of to the 
newsgroup prominently into the GUI)


You're very welcome. The reason foreach(int i, x; argTuple) 
failed is because argTuple is a value (of type T), and so known 
only at run-time. To get a foreach to run at compile-time, you 
have to give it something whose value is known to the compiler 
(so, T and typeof(argTuple) would suffice, and 0..T.length really 
should as well).


A nice way to test is pragma(msg, Foo) where Foo is your 
argument... if its knowable at compile-time, then your compiler 
should output Foo (or the name of whatever its aliasing) to the 
console.


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread TheFlyingFiddle via Digitalmars-d-learn

On Monday, 21 July 2014 at 15:04:14 UTC, TheFlyingFiddle wrote:

//Outputs 1 to 10 at compile-time.

Edit: 0 to 9



Re: Map one tuple to another Tuple of different type

2014-07-21 Thread Daniel Gibson via Digitalmars-d-learn

Am 21.07.2014 17:04, schrieb TheFlyingFiddle:

On Monday, 21 July 2014 at 01:42:58 UTC, Daniel Gibson wrote:

Am 21.07.2014 03:34, schrieb Vlad Levenfeld:

To get a foreach to run at compile-time, you have to give it something
whose value is known to the compiler (so, T and typeof(argTuple) would
suffice, and 0..T.length really should as well).


Yup


I use this when i want a compile time foreach(from a constant number).
It's slightly longer but has worked great for me thus far.

template staticIota(size_t s, size_t e, size_t step = 1)
{
 import std.typetuple : TypeTuple;
 static if(s  e)
 alias staticIota = TypeTuple!(s, staticIota!(s + step, e));
 else
 alias staticIota = TypeTuple!();
}


Yeah, I had a similar workaround:

template TupleIndicesImpl(alias len, I...)
{
  static if(len == I.length) // also handles len == 0
alias TupleIndicesImpl = I;
  else static if(I.length == 0)
alias TupleIndicesImpl = TupleIndicesImpl!(len, 0);
  else // I contains 0 ... I.length - 1, so add I.length
alias TupleIndicesImpl = TupleIndicesImpl!(len, I, I.length);
}

template TupleIndices(alias len)
{
  alias TupleIndices = TupleIndicesImpl!(len);
}

foreach(i; TupleIndices!(myTuple.length) { ... }

At least for iterating over a tuple Vlad's way suggestion
(foreach(i, U; TupleType)) is nicer and more concise.

However, having something like staticIota in the stdlib would probably 
make sense.


Cheers,
Daniel


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Jul 21, 2014 at 12:55:34AM +0200, Daniel Gibson via Digitalmars-d-learn 
wrote:
 Hi,
 I have a variadic templated function and want to call a C varargs function.
 I want to be able to pass static arrays, which D2 passes by value and C by
 reference, so I'd like to automagically translate those arguments.
 
 My idea was something like this:
 
   extern (C) origFun(int x, ...);
 
   T transTupleElem(T)(T arg) { return arg; }
 
   float* transTupleElem(T : float[3])(T arg) {
 return arg.ptr;
   }
 
   void fun(T...)(int x, T argTuple) {
 // create a new tuple type that replaces all static float[3]
 // arrays with float* to emulate C call-by-reference behavior
 alias ReplaceAll!(float[3], float*, T) ModifiedTuple;
 ModifiedTuple modTuple;
 
 foreach(size_t i ; 0 .. T.length)
   modTuple[i] = transTupleElem(argTuple[i]); // BOOM!
 
 origFun(modTuple); // or is it modTuple.expand ?
   }
 
 However, this doesn't work (dmd 2.065 linux64), because:
 Error: variable i cannot be read at compile time
[...]

Try this:

import std.typecons : staticIota;
foreach (i; staticIota!(0, T.length))
modTuple[i] = transTupleElem(argTuple[i]);


T

-- 
The volume of a pizza of thickness a and radius z can be described by the 
following formula: pi zz a. -- Wouter Verhelst


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Jul 21, 2014 at 06:36:04PM +0200, Daniel Gibson via Digitalmars-d-learn 
wrote:
[...]
 However, having something like staticIota in the stdlib would probably
 make sense.
[...]

It's already in std.typecons.

(Admittedly, that's not exactly the most obvious place to look for it...)


T

-- 
There are two ways to write error-free programs; only the third one works.


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread bearophile via Digitalmars-d-learn

H. S. Teoh:


It's already in std.typecons.


But it is not online yet?

Bye,
bearophile


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread Daniel Gibson via Digitalmars-d-learn

Am 21.07.2014 20:09, schrieb H. S. Teoh via Digitalmars-d-learn:

On Mon, Jul 21, 2014 at 06:36:04PM +0200, Daniel Gibson via Digitalmars-d-learn 
wrote:
[...]

However, having something like staticIota in the stdlib would probably
make sense.

[...]

It's already in std.typecons.

(Admittedly, that's not exactly the most obvious place to look for it...)


T



static.typecons is actually where I would have expected it, as it 
constructs a tuple.. but it isn't mentioned on 
http://dlang.org/library/std/typecons.html or 
http://dlang.org/phobos/std_typecons.html
and at least in my /usr/include/dmd/phobos/std/typecons.d (2.065) it's 
private:

private template staticIota(int beg, int end)
{ ... }
And it seems like I can't use it.
Anyway, good to know that it exists and hopefully future versions of D2 
make that function public, so thanks for showing up another alternative 
to solve my problem :-)


BTW: The name Iota is horrible.. it doesn't describe at all what the 
function does.
And But C++11 STL has a function of the same name that does the same 
thing or some obscure programming language from the 60ies (APL) used 
the Greek iota letter to do this is no excuse, one shouldn't expect 
potential D users to know about that (even after using C++ for years I 
never encountered std::iota..)

Maybe Numerate or something like that would be more descriptive..

Cheers,
Daniel


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread John Colvin via Digitalmars-d-learn
On Monday, 21 July 2014 at 18:10:14 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
On Mon, Jul 21, 2014 at 12:55:34AM +0200, Daniel Gibson via 
Digitalmars-d-learn wrote:

Hi,
I have a variadic templated function and want to call a C 
varargs function.
I want to be able to pass static arrays, which D2 passes by 
value and C by
reference, so I'd like to automagically translate those 
arguments.


My idea was something like this:

  extern (C) origFun(int x, ...);

  T transTupleElem(T)(T arg) { return arg; }

  float* transTupleElem(T : float[3])(T arg) {
return arg.ptr;
  }

  void fun(T...)(int x, T argTuple) {
// create a new tuple type that replaces all static 
float[3]
// arrays with float* to emulate C call-by-reference 
behavior

alias ReplaceAll!(float[3], float*, T) ModifiedTuple;
ModifiedTuple modTuple;

foreach(size_t i ; 0 .. T.length)
  modTuple[i] = transTupleElem(argTuple[i]); // BOOM!

origFun(modTuple); // or is it modTuple.expand ?
  }

However, this doesn't work (dmd 2.065 linux64), because:
Error: variable i cannot be read at compile time

[...]

Try this:

import std.typecons : staticIota;
foreach (i; staticIota!(0, T.length))
modTuple[i] = transTupleElem(argTuple[i]);


T


staticIota is marked package in std.typecons


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread Vlad Levenfeld via Digitalmars-d-learn
On Monday, 21 July 2014 at 19:02:59 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
functionality is desirable. Maybe we should rouse a racket on 
the main D
forum to either make staticIota public, or implement static 
foreach. ;-)


static switch would be so sick. I frequently find myself doing 
some compile-time branching with more than 2 branches or with an 
enum (like for policies/strategies/whatever). Compile-time case 
labels would clean that code up, and final switch would be a 
maintenance improvement as well.


static while sounds cool, but how would it work? (as in use case, 
not implementation). The condition would have to be immutable, 
wouldn't it?


Re: Map one tuple to another Tuple of different type

2014-07-21 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jul 22, 2014 at 02:47:51AM +, Vlad Levenfeld via 
Digitalmars-d-learn wrote:
 On Monday, 21 July 2014 at 19:02:59 UTC, H. S. Teoh via Digitalmars-d-learn
 wrote:
 functionality is desirable. Maybe we should rouse a racket on the
 main D forum to either make staticIota public, or implement static
 foreach. ;-)
 
 static switch would be so sick. I frequently find myself doing some
 compile-time branching with more than 2 branches or with an enum (like
 for policies/strategies/whatever). Compile-time case labels would
 clean that code up, and final switch would be a maintenance
 improvement as well.
 
 static while sounds cool, but how would it work? (as in use case, not
 implementation). The condition would have to be immutable, wouldn't
 it?

I don't know about use cases in general, but one place where it comes in
handy is in iterating over template argument lists (type tuples).
Currently, I have to resort to:

Tuple!(int,int,int,int,int) fields;
foreach (i; staticIota!(0, n))
{
fields[i]++; // for example
}

Which is not bad for simple operations, but would be cleaner if we had
static while / static foreach.


T

-- 
We've all heard that a million monkeys banging on a million typewriters will 
eventually reproduce the entire works of Shakespeare.  Now, thanks to the 
Internet, we know this is not true. -- Robert Wilensk