Re: Supporting and signature-checking all foreach variations

2012-02-26 Thread Ali Çehreli

On 02/25/2012 08:25 AM, Ashish Myles wrote:
 I want to define a general-purpose centroid computer for point containers
 and ran into a couple of challenges. Firstly, here is the basic code

  Point3 computeCentroid(PointContainer)(const ref PointContainer C)
  if (...)// want a signature constraint for usability of 
foreach

  {
  Point3 c = Point3(0.0, 0.0, 0.0);
  size_t total = 0;
  foreach(Point3 p; C) {   // enforce that the container 
supports this

  c += p; ++total;
  }
  if (total  0)
  c /= cast(double)(total);
  return c;
  }

...

 2. Secondly, TDPL on page 381 says that foreach iterates over C[], if
C defines the opSlice() function without any arguments.

Although what you describe also seems useful, that heading seems to be 
about ranges and specifically about the three InputRange functions. The 
feature has indeed been implemented recently:


  http://d.puremagic.com/issues/show_bug.cgi?id=5605

However the code above doesn't seem to work and requires me to
explicitly invoke the slice operator myself like
  foreach(p; C[]) { ... }
when my data structure clearly defines the following functions.
  Point3[] opSlice() { return _cpts[]; }
  const (Point3)[] opSlice() const { return _cpts[]; }
Is this a misunderstanding on my part or an unimplemented feature?

But I've just verified that the following works with dmd 2.058:

import std.stdio;

struct Point3
{}

struct MyCollection
{
Point3[] _cpts;

Point3[] opSlice() { return _cpts; }  // -- _cpts[] works too

const (Point3)[] opSlice() const { return _cpts; }
}

void main()
{
auto coll = MyCollection();

foreach (i; coll) {
// ...
}
}

Ali



Re: Supporting and signature-checking all foreach variations

2012-02-26 Thread Ashish Myles
On Sun, Feb 26, 2012 at 5:25 AM, Ali Çehreli acehr...@yahoo.com wrote:
 On 02/25/2012 08:25 AM, Ashish Myles wrote:
    However the code above doesn't seem to work and requires me to
    explicitly invoke the slice operator myself like
      foreach(p; C[]) { ... }
    when my data structure clearly defines the following functions.
      Point3[] opSlice() { return _cpts[]; }
      const (Point3)[] opSlice() const { return _cpts[]; }
    Is this a misunderstanding on my part or an unimplemented feature?

 But I've just verified that the following works with dmd 2.058:

 import std.stdio;

 struct Point3
 {}

 struct MyCollection
 {
    Point3[] _cpts;

    Point3[] opSlice() { return _cpts; }  // -- _cpts[] works too

    const (Point3)[] opSlice() const { return _cpts; }
 }

 void main()
 {
    auto coll = MyCollection();

    foreach (i; coll) {
        // ...
    }
 }


Oh good to know. I had downgraded my dmd after some new CTFE bugs
resulted in compilation errors on some of my code, and hadn't thought
to check with the latest version.


Re: Supporting and signature-checking all foreach variations

2012-02-25 Thread Alex Rønne Petersen

On 25-02-2012 17:25, Ashish Myles wrote:

I want to define a general-purpose centroid computer for point containers
and ran into a couple of challenges. Firstly, here is the basic code

 Point3 computeCentroid(PointContainer)(const ref PointContainer C)
 if (...)// want a signature constraint for usability of foreach
 {
 Point3 c = Point3(0.0, 0.0, 0.0);
 size_t total = 0;
 foreach(Point3 p; C) {   // enforce that the container supports this
 c += p; ++total;
 }
 if (total  0)
 c /= cast(double)(total);
 return c;
 }

I want to have the most generally-applicable version of this functionality
(for const/immutable/etc containers supporting foreach in various ways),
ideally without needing to write multiple versions of this function.

1. Since support for foreach can be added in many ways (with
   ref/non-ref/const variants), I wanted to check if there was any
   signature constraint that could check if the container supports foreach
   as above. I looked into the compiles traits, but that doesn't work for
   statements.

   For an opAssign version, I had tried
 if (is(typeof(C.opApply(delegate(const ref Point3) { return 1;}
   but this is unelegant because the container's opApply could have instead
   supplied delegate(Point3) or delegate(ref Point3) (although the latter
   would require me to not use a const on the parameter declaration).

2. Secondly, TDPL on page 381 says that foreach iterates over C[], if
   C defines the opSlice() function without any arguments.
   However the code above doesn't seem to work and requires me to
   explicitly invoke the slice operator myself like
 foreach(p; C[]) { ... }
   when my data structure clearly defines the following functions.
 Point3[] opSlice() { return _cpts[]; }
 const (Point3)[] opSlice() const { return _cpts[]; }
   Is this a misunderstanding on my part or an unimplemented feature?

3. A more general question: Is there any by any chance a way to avoid the
   redundancy above of defining two opSlice() functions (or two opAssign()
   functions if I went that route -- one for const and another for ref)?
   I suspect that the answer is no, but I just wanted to verify.


I think std.traits.isIterable(T) is what you want.

--
- Alex


Re: Supporting and signature-checking all foreach variations

2012-02-25 Thread Ashish Myles
On Sat, Feb 25, 2012 at 11:37 AM, Alex Rønne Petersen
xtzgzo...@gmail.com wrote:
 On 25-02-2012 17:25, Ashish Myles wrote:

 1. Since support for foreach can be added in many ways (with
   ref/non-ref/const variants), I wanted to check if there was any
   signature constraint that could check if the container supports foreach
   as above. I looked into the compiles traits, but that doesn't work for
   statements.

 I think std.traits.isIterable(T) is what you want.


Great! Now that I know the answer to the first question, it is so easy
to find the answer on google :P .   Technically, I want something like
isIterable(T,Point3); given the definition of isIterable, I can easily
get this functionality.

I am still looking for answers to the second question (which might
indicate a bug in the frontend) and third question whose answer would
be really enlightening if what I requested is possible.


Re: Supporting and signature-checking all foreach variations

2012-02-25 Thread Dmitry Olshansky

On 25.02.2012 20:25, Ashish Myles wrote:

I want to define a general-purpose centroid computer for point containers
and ran into a couple of challenges. Firstly, here is the basic code

 Point3 computeCentroid(PointContainer)(const ref PointContainer C)
 if (...)// want a signature constraint for usability of foreach
 {
 Point3 c = Point3(0.0, 0.0, 0.0);
 size_t total = 0;
 foreach(Point3 p; C) {   // enforce that the container supports this
 c += p; ++total;
 }
 if (total  0)
 c /= cast(double)(total);
 return c;
 }

I want to have the most generally-applicable version of this functionality
(for const/immutable/etc containers supporting foreach in various ways),
ideally without needing to write multiple versions of this function.

1. Since support for foreach can be added in many ways (with
   ref/non-ref/const variants), I wanted to check if there was any
   signature constraint that could check if the container supports foreach
   as above. I looked into the compiles traits, but that doesn't work for
   statements.

   For an opAssign version, I had tried
 if (is(typeof(C.opApply(delegate(const ref Point3) { return 1;}
   but this is unelegant because the container's opApply could have instead
   supplied delegate(Point3) or delegate(ref Point3) (although the latter
   would require me to not use a const on the parameter declaration).

2. Secondly, TDPL on page 381 says that foreach iterates over C[], if
   C defines the opSlice() function without any arguments.
   However the code above doesn't seem to work and requires me to
   explicitly invoke the slice operator myself like
 foreach(p; C[]) { ... }
   when my data structure clearly defines the following functions.
 Point3[] opSlice() { return _cpts[]; }
 const (Point3)[] opSlice() const { return _cpts[]; }
   Is this a misunderstanding on my part or an unimplemented feature?


It's supposed to work.
I think it's just not implemented yet.



3. A more general question: Is there any by any chance a way to avoid the
   redundancy above of defining two opSlice() functions (or two opAssign()
   functions if I went that route -- one for const and another for ref)?
   I suspect that the answer is no, but I just wanted to verify.



--
Dmitry Olshansky


Re: Supporting and signature-checking all foreach variations

2012-02-25 Thread Jesse Phillips

On Saturday, 25 February 2012 at 16:26:05 UTC, Ashish Myles wrote:

2. Secondly, TDPL on page 381 says that foreach iterates over 
C[], if

  C defines the opSlice() function without any arguments.
  However the code above doesn't seem to work and requires me to
  explicitly invoke the slice operator myself like
foreach(p; C[]) { ... }
  when my data structure clearly defines the following 
functions.

Point3[] opSlice() { return _cpts[]; }
const (Point3)[] opSlice() const { return _cpts[]; }
  Is this a misunderstanding on my part or an unimplemented 
feature?


Is not implemented, not seeing a bug report
http://d.puremagic.com/issues/

3. A more general question: Is there any by any chance a way to 
avoid the
  redundancy above of defining two opSlice() functions (or two 
opAssign()
  functions if I went that route -- one for const and another 
for ref)?

  I suspect that the answer is no, but I just wanted to verify.


Not sure look into information on 'auto ref' and 'inout' these
were built for removing duplications of const and ref functions.
These have had some work done to make them functional, but could
still have holes.