Re: Is there a way to set an alias to specific form of a template?

2011-10-08 Thread Ali Çehreli
On Fri, 07 Oct 2011 18:29:26 -0700, Roderick Gibson wrote:

 This may be the completely wrong approach, but I am basically thinking
 of something like this (I am aware this will not compile, it's
 psuedocode):
 
 class Vector(T) {
   ... //definition here
 }
 
 alias Vector(float, float) vec2f;
 auto v = new vec2f(1.0,1.0);
 
 I am making a templated Vector class (a mathematical vector) that will
 have varying types (thus a template) and dimensions (via variadic
 functions), so that the same template definition will work for 2d or 3d
 vectors (or 4d, etc).

 I then want the programmer to be able to define
 the specific forms that he wants so he can easily keep track of them
 (without getting confused about which is a 2d integer vector and which
 is a 3d float vector), and then use those forms in a type safe manner.
 Is this even possible? If it is, but it's the wrong way to do it, what's
 the right way?
 
 Basically I wanted to write it once and not worry about writing it again
 to handle different types and dimensions (no vec2i class, or vec2f, or
 vec3f, or vec3i, etc). Templates easily handles the type requirement,
 but what about the dimensional requirement? Am I just going to have to
 rewrite it when I add dimensions?

You can take advantage of 'Template Value Parameters' and 'Typesafe 
Variadic Functions':

  http://www.d-programming-language.org/
template.html#TemplateValueParameter

  http://www.d-programming-language.org/function.html

class Vector(T, int N)
{
T[N] elements;

this(T[] elements ...)
{
this.elements = elements;
}
}

alias Vector!(double, 2) Vec2D;
alias Vector!(double, 3) Vec3D;

void main()
{
auto v2d = new Vec2D(2.2, 2.2);
auto v3d = new Vec3D(3.3, 3.3, 3.3);

// Alternatively, all parameters at once:
auto v3d_too = new Vec3D([ 33, 33, 33, ]);
}

(Some would find 'size_t N' to be more appropriate since N is a 
dimension.)

Ali


Re: Is there a way to set an alias to specific form of a template?

2011-10-08 Thread Roderick Gibson

On 10/7/2011 7:33 PM, Andrej Mitrovic wrote:

You don't have to rewrite Vector for multiple dimensions, methinks:

class Vector(T...) {
 this(T t) {}
}

void main()
{
 alias Vector!(float, float) vec2f;
 auto v = new vec2f(1.0,1.0);
}

You'll probably have to play with `static if`, template constraints,
and stuff like that.


I got this working, found an odd bug though. This code,

alias Vector!(float, float) vec2f;
alias Vector!(double, double) vec2d;
alias Vector!(float, float, float) vec3f;

public struct Vector(T...) {
int dim = 0;

this(T...)(T args) {
dim = args.length;
}

unittest {
auto v = new vec2f(1.2f, 1.5f);
vec2f d = new vec2f(1.1f, 1.4f);

assert(v.dim == 2);
assert(d.dim == 2);
}
}

will pass the first assert and fail on the second. Checking out the 
contents of v.length and d.length with writeln gives the correct answer 
on the first and

2
1
RANDOMHEXCODE
on the second. Very strange.


Re: Is there a way to set an alias to specific form of a template?

2011-10-08 Thread Philippe Sigaud
On Sat, Oct 8, 2011 at 08:43, Roderick Gibson knit...@gmail.com wrote:


A possible problem (or feature ?) with the Vector(T...) code is that
you could possibly create a Vector!(int, float, string), for example.
Even with template constraints to limit the inner types to numerical
types, this template has too much freedom, I think : Vector!(float,
int, short) is a strange type for a vector.
I'd go the Vector(Type, int length) way myself. Or even Matrix(Type,
nRows, nCol) or somesuch.


 I got this working, found an odd bug though. This code,

 alias Vector!(float, float) vec2f;
 alias Vector!(double, double) vec2d;
 alias Vector!(float, float, float) vec3f;

 public struct Vector(T...) {
        int dim = 0;

        this(T...)(T args) {
                dim = args.length;
        }

        unittest {
                auto v = new vec2f(1.2f, 1.5f);
                vec2f d = new vec2f(1.1f, 1.4f);

                assert(v.dim == 2);
                assert(d.dim == 2);

 }

 will pass the first assert and fail on the second. Checking out the contents
 of v.length and d.length with writeln gives the correct answer on the first
 and
 2
 1
 RANDOMHEXCODE
 on the second. Very strange.

You Vector is a struct, a value type in D. Do not 'new' structs, as
you'd do in C++ (in D, you'll use new only for classes or reference
types in general)
Given a struct S, new S() has type S*. I think in:

vec2f d = new vec2f(...);

You create a vec2f and try to assign a vec2f* to it.

Try this, it should work:

        unittest {
                auto v =  vec2f(1.2f, 1.5f);
                vec2f d =  vec2f(1.1f, 1.4f);

                assert(v.dim == 2);
                assert(d.dim == 2);
   }


Re: Is there a way to set an alias to specific form of a template?

2011-10-08 Thread Roderick Gibson

On 10/7/2011 11:35 PM, Ali Çehreli wrote:

On Fri, 07 Oct 2011 18:29:26 -0700, Roderick Gibson wrote:


This may be the completely wrong approach, but I am basically thinking
of something like this (I am aware this will not compile, it's
psuedocode):

class Vector(T) {
... //definition here
}

alias Vector(float, float) vec2f;
auto v = new vec2f(1.0,1.0);

I am making a templated Vector class (a mathematical vector) that will
have varying types (thus a template) and dimensions (via variadic
functions), so that the same template definition will work for 2d or 3d
vectors (or 4d, etc).

I then want the programmer to be able to define
the specific forms that he wants so he can easily keep track of them
(without getting confused about which is a 2d integer vector and which
is a 3d float vector), and then use those forms in a type safe manner.
Is this even possible? If it is, but it's the wrong way to do it, what's
the right way?

Basically I wanted to write it once and not worry about writing it again
to handle different types and dimensions (no vec2i class, or vec2f, or
vec3f, or vec3i, etc). Templates easily handles the type requirement,
but what about the dimensional requirement? Am I just going to have to
rewrite it when I add dimensions?


You can take advantage of 'Template Value Parameters' and 'Typesafe
Variadic Functions':

   http://www.d-programming-language.org/
template.html#TemplateValueParameter

   http://www.d-programming-language.org/function.html

class Vector(T, int N)
{
 T[N] elements;

 this(T[] elements ...)
 {
 this.elements = elements;
 }
}

alias Vector!(double, 2) Vec2D;
alias Vector!(double, 3) Vec3D;

void main()
{
 auto v2d = new Vec2D(2.2, 2.2);
 auto v3d = new Vec3D(3.3, 3.3, 3.3);

 // Alternatively, all parameters at once:
 auto v3d_too = new Vec3D([ 33, 33, 33, ]);
}

(Some would find 'size_t N' to be more appropriate since N is a
dimension.)

Ali


I decided this would be the best way, thank you. One question though, I 
noticed with this method that you can only assert that the dimension and 
the parameter list length match at runtime (ie, someone could 
instantiate a vec2d as vec2d(2.2, 2.2, 3.1) and the compiler will 
happily accept it), I'm guessing constraints are what's needed, but I 
don't know how to get the parameter count at compile time, only at 
runtime (via elements.length). The compiler *should* know the length at 
compile time shouldn't it?


I managed to get it to at least stop the compilation with

this(T[N] elements...)

but the error messages are terrible. Is there a better way, perhaps 
using a static assert?


Re: Is there a way to set an alias to specific form of a template?

2011-10-08 Thread bearophile
Andrej Mitrovic:

 There's an LGPL-licensed Vector module here:
 https://github.com/Zardoz89/zmath/blob/master/src/vector.d
 
 Not mine, but it's interesting.

Eventually Phobos will contain fast 2D/3D/4D vector type, because they are used 
often in games, programs that need 2D geometry, various simulations, etc.

Bye,
bearophile


Re: Is there a way to set an alias to specific form of a template?

2011-10-08 Thread Andrej Mitrovic
I would go with Ali Çehreli's example instead of the variadic type
example I gave, I think it could simplify code quite a bit.


Pointers and Ranges

2011-10-08 Thread Xinok
I'm new to ranges and while I understand the basic concept, I don't know 
everything about them. With arrays, you can simply use arr.ptr to infer 
a type automatically. So I was wondering, is there an equivalent for 
ranges? What I'm looking for is the ability to do *p as well as p[1] or 
p[-1] with ranges.


Re: Is there a way to set an alias to specific form of a template?

2011-10-08 Thread Ali Çehreli
On Sat, 08 Oct 2011 03:52:25 -0700, Roderick Gibson wrote:

 On 10/7/2011 11:35 PM, Ali Çehreli wrote:
 On Fri, 07 Oct 2011 18:29:26 -0700, Roderick Gibson wrote:

 This may be the completely wrong approach, but I am basically thinking
 of something like this (I am aware this will not compile, it's
 psuedocode):

 class Vector(T) {
 ... //definition here
 }

 alias Vector(float, float) vec2f;
 auto v = new vec2f(1.0,1.0);

 I am making a templated Vector class (a mathematical vector) that will
 have varying types (thus a template) and dimensions (via variadic
 functions), so that the same template definition will work for 2d or
 3d vectors (or 4d, etc).

 I then want the programmer to be able to define the specific forms
 that he wants so he can easily keep track of them (without getting
 confused about which is a 2d integer vector and which is a 3d float
 vector), and then use those forms in a type safe manner. Is this even
 possible? If it is, but it's the wrong way to do it, what's the right
 way?

 Basically I wanted to write it once and not worry about writing it
 again to handle different types and dimensions (no vec2i class, or
 vec2f, or vec3f, or vec3i, etc). Templates easily handles the type
 requirement, but what about the dimensional requirement? Am I just
 going to have to rewrite it when I add dimensions?

 You can take advantage of 'Template Value Parameters' and 'Typesafe
 Variadic Functions':

http://www.d-programming-language.org/
 template.html#TemplateValueParameter

http://www.d-programming-language.org/function.html

 class Vector(T, int N)
 {
  T[N] elements;

  this(T[] elements ...)
  {
  this.elements = elements;
  }
 }

 alias Vector!(double, 2) Vec2D;
 alias Vector!(double, 3) Vec3D;

 void main()
 {
  auto v2d = new Vec2D(2.2, 2.2);
  auto v3d = new Vec3D(3.3, 3.3, 3.3);

  // Alternatively, all parameters at once: auto v3d_too = new
  Vec3D([ 33, 33, 33, ]);
 }

 (Some would find 'size_t N' to be more appropriate since N is a
 dimension.)

 Ali
 
 I decided this would be the best way, thank you. One question though, I
 noticed with this method that you can only assert that the dimension and
 the parameter list length match at runtime (ie, someone could
 instantiate a vec2d as vec2d(2.2, 2.2, 3.1) and the compiler will
 happily accept it), I'm guessing constraints are what's needed, but I
 don't know how to get the parameter count at compile time, only at
 runtime (via elements.length). The compiler *should* know the length at
 compile time shouldn't it?
 
 I managed to get it to at least stop the compilation with
 
 this(T[N] elements...)

I didn't know that would work. :)

 but the error messages are terrible. Is there a better way, perhaps
 using a static assert?

Here is some ugly code that accepts either T[N] or N Ts. Note that the 
constructor now takes T[N], not T[N]...:

import std.stdio;
import std.string;
import std.conv;

string ctor_with_params(T, int N)()
{
string param_list;
foreach (i; 0 .. N) {
if (i != 0) {
param_list ~= , ;
}
param_list ~= T.stringof ~  p ~ to!string(i);
}

string code = this( ~ param_list ~ ) { elements = [  ;

foreach (i; 0 .. N) {
if (i != 0) {
code ~= , ;
}
code ~= p ~ to!string(i);
}

code ~=  ]; };

return code;
}

unittest
{
writeln(ctor_with_params!(double, 3)());
}

class Vector(T, int N)
{
T[N] elements;

this(T[N] elements)
{
this.elements = elements;
}

mixin(ctor_with_params!(T, N)());
}

alias Vector!(double, 3) Vec3D;

void main()
{
auto v0 = new Vec3D(  33, 33, 33,  );
auto v1 = new Vec3D([ 33, 33, 33, ]);

/*
  Error: constructor deneme.Vector!(double,3).Vector.this (double[3LU]
  elements) is not callable using argument types (int,int)
*/
// auto v2 = new Vec3D(  33, 33  );


/*
  Error: constructor deneme.Vector!(double,3).Vector.this (double[3LU]
  elements) is not callable using argument types (int[])

  Error: cannot implicitly convert expression ([33,33,33,33]) of type 
int[]
  to double

  Error: expected 3 function arguments, not 1
*/
// auto v3 = new Vec3D([ 33, 33, 33, 33 ]);
}

It prints the mixed-in N-parameter constructor:

this(double p0, double p1, double p2) { elements = [ p0, p1, p2 ]; }

If you don't need the T[N] constructor at all, the best approach could be 
removing it. Then the error messages make more sense:

class Vector(T, int N)
{
T[N] elements;

mixin(ctor_with_params!(T, N)());
}

Ali


Re: Pointers and Ranges

2011-10-08 Thread Ali Çehreli
On Sat, 08 Oct 2011 12:31:20 -0400, Xinok wrote:

 I'm new to ranges and while I understand the basic concept, I don't know
 everything about them. With arrays, you can simply use arr.ptr to infer
 a type automatically.

Or with ElementType. If Range is a template type:

   writefln(I have a range of %ss, (ElementType!Range).stringof);
// for example, I have a range of ints

 So I was wondering, is there an equivalent for
 ranges? What I'm looking for is the ability to do *p

Depending on the range it can be

- myRange.front
- myRange.back
- myRange[i]

 as well as p[1] or

Only with RandomAccessRanges.

 p[-1] with ranges.

That should be considered out of bounds with ranges, but it is possible 
to achieve with opIndex() for RandomAccessRanges.

Ali

P.S. I am in the process of translating my Turkish D book to English. 
Since it targets the beginner programmer and starts from the very basics, 
it may be a little boring for some. But I had decided to skip some 
chapters and start translating more interesting ones that normally come 
later in the book. The two chapters on Ranges happen to be the ones that 
I am currently working on. I may make the current state of the 
translation available in a few days. Here are the originals:

  http://ddili.org/ders/d/araliklar.html

  http://ddili.org/ders/d/araliklar_baska.html

There is a Google translate bar on the left hand side with very limited 
results. (Humans are still better than computers! :))

Here is a little ForwardRange example:

import std.stdio;
import std.range;

struct FibonacciSeries
{
int first = 0;
int second = 1;

static enum empty = false;
// Alternatively: static immutable bool empty = false;

@property int front() const
{
return first;
}

void popFront()
{
int third = first + second;
first = second;
second = third;
}

FibonacciSeries save() const
{
return this;
}
}

void main()
{
writeln(take(FibonacciSeries(), 10));
}