Re: Generic collection/element function signatures in D2 versus D1

2010-09-11 Thread Brad Roberts
On 9/11/2010 9:32 PM, Nick Sabalausky wrote:
> "Jacob Carlborg"  wrote in message 
> news:i5t61q$2j7...@digitalmars.com...
>>
>> If you're not going to modify the content of the array I think this will 
>> work:
>>
>> void foo (T) (const(T)[] collection, T elem) {}
>>
>> This will allow both mutable, immutable and const arrays. But it will not 
>> let you modify the array like this:
>>
>> collection[3] = 'a';
>>
> 
> On DMD 2.048, This isn't working for me:
> 
> -
> void foo(T)(const(T)[] coll, T elem)
> {
> }
> 
> void main()
> {
> string x = "hello";
> foo(x, x[1]);
> }
> 
> -
> 
> Result:
> -
> testStringAndChar.d(8): Error: template testStringAndChar.foo(T) does not 
> match any function template declaration
> testStringAndChar.d(8): Error: template testStringAndChar.foo(T) cannot 
> deduce template function from argument types !()(string,immutable(char))
> -
> 
> I figured that was just because 'const(immutable(T))[]' doesn't make much 
> sence, so I tried this and got the exact same error messages:
> 
> -
> import std.traits;
> 
> void foo(T)(const(Unqual!T)[] coll, T elem)
> {
> }
> 
> void main()
> {
> string x = "hello";
> foo(x, x[1]);
> }
> -
> 
> It seems to be a problem with IFTI, because this does work with both 
> versions:
> foo!char(x, x[1]);
> 
> Kind of a pain.
> 

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



Re: Generic collection/element function signatures in D2 versus D1

2010-09-11 Thread Nick Sabalausky
"Jacob Carlborg"  wrote in message 
news:i5t61q$2j7...@digitalmars.com...
>
> If you're not going to modify the content of the array I think this will 
> work:
>
> void foo (T) (const(T)[] collection, T elem) {}
>
> This will allow both mutable, immutable and const arrays. But it will not 
> let you modify the array like this:
>
> collection[3] = 'a';
>

On DMD 2.048, This isn't working for me:

-
void foo(T)(const(T)[] coll, T elem)
{
}

void main()
{
string x = "hello";
foo(x, x[1]);
}

-

Result:
-
testStringAndChar.d(8): Error: template testStringAndChar.foo(T) does not 
match any function template declaration
testStringAndChar.d(8): Error: template testStringAndChar.foo(T) cannot 
deduce template function from argument types !()(string,immutable(char))
-

I figured that was just because 'const(immutable(T))[]' doesn't make much 
sence, so I tried this and got the exact same error messages:

-
import std.traits;

void foo(T)(const(Unqual!T)[] coll, T elem)
{
}

void main()
{
string x = "hello";
foo(x, x[1]);
}
-

It seems to be a problem with IFTI, because this does work with both 
versions:
foo!char(x, x[1]);

Kind of a pain.




Re: Generic collection/element function signatures in D2 versus D1

2010-09-08 Thread Steven Schveighoffer

On Wed, 08 Sep 2010 12:38:44 -0400, Pelle  wrote:


On 09/08/2010 02:24 PM, Steven Schveighoffer wrote:

On Tue, 07 Sep 2010 14:06:58 -0400, Steven Schveighoffer
 wrote:


On Tue, 07 Sep 2010 11:37:20 -0400, Pelle 
wrote:


On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:

Yes, a valid return. Your function should be:

void foo(void delegate(const(C) f) const

It helps to understand that inout/const/immutable has NOTHING to do
with
code generation, it only has to do with limiting what compiles. For
this
reason, an inout function is compiled once, and works on all three
constancies (4 if you have a nested inout function). For the entire
function any inout variable is treated as a non-changeable value,  
just
like const. Then when you return, it's converted at the call site  
back
to the constancy with which it was called. If the return value is  
void,
then there's nothing to convert, and no reason to use inout over  
const.


I'll repeat -- there is no benefit to inout if you are not returning
anything.

-Steve


That's not an equivalent function signature. Or maybe it is, but look
at this (sorry it's so long):

class C {
int x;
this(int y) { x = y; }

inout(int*) foo() inout {
return &x;
}
void bar(void delegate(int*) f) {
f(&x);
}
void bar(void delegate(const(int*)) f) const {
f(&x);
}
void bar(void delegate(immutable(int*)) f) immutable {
f(&x);
}
}

void main() {

immutable(int)* wah;
void wahwah(immutable(int*) x) {
wah = x;
}
auto c = new immutable(C)(10);
wahwah(c.foo); // why is this privilegied with inout
c.bar(&wahwah); // and this not?

writeln(*wah);

}

Can't use void delegate(const(int*)) there.


Thanks for clarifying, I didn't quite understand the usage before.

This is a limitation of inout's design. Technically inout requires a
single inout output, and can have multiple inout inputs. Your example
matches that description, so in theory it's possible.


I realized last night that this won't work. Simple reason -- during an
inout function, the function promises to treat the arguments as if they
were const.

If your class instance was mutable, this would not be true, e.g.:

class C
{
int x;
void bar(void delegate(inout(int)* f) inout { f(&x); }
}

void main() {

auto c = new C;
void dg(int *f) {*f = 10;}
c.bar(&dg); // modifies c, even though the function is marked as inout
}

-Steve


Well, inout was conceived as a counter to where you need to write the  
exact same function for every type of constness, was it not? :-)


Not exactly, it was conceived as a solution for the case where you would  
normally write a const function, but you don't want it to alter your const  
contract with the object in question.  Basically, you want a function that  
promises not to alter the parameters, but gives you back one of your  
parameters or a portion of one of them in the same constancy you pass in.   
The classic example is a property getter.


If you are not returning a portion of the input, then you can use const  
instead.


-Steve


Re: Generic collection/element function signatures in D2 versus D1

2010-09-08 Thread Pelle

On 09/08/2010 02:24 PM, Steven Schveighoffer wrote:

On Tue, 07 Sep 2010 14:06:58 -0400, Steven Schveighoffer
 wrote:


On Tue, 07 Sep 2010 11:37:20 -0400, Pelle 
wrote:


On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:

Yes, a valid return. Your function should be:

void foo(void delegate(const(C) f) const

It helps to understand that inout/const/immutable has NOTHING to do
with
code generation, it only has to do with limiting what compiles. For
this
reason, an inout function is compiled once, and works on all three
constancies (4 if you have a nested inout function). For the entire
function any inout variable is treated as a non-changeable value, just
like const. Then when you return, it's converted at the call site back
to the constancy with which it was called. If the return value is void,
then there's nothing to convert, and no reason to use inout over const.

I'll repeat -- there is no benefit to inout if you are not returning
anything.

-Steve


That's not an equivalent function signature. Or maybe it is, but look
at this (sorry it's so long):

class C {
int x;
this(int y) { x = y; }

inout(int*) foo() inout {
return &x;
}
void bar(void delegate(int*) f) {
f(&x);
}
void bar(void delegate(const(int*)) f) const {
f(&x);
}
void bar(void delegate(immutable(int*)) f) immutable {
f(&x);
}
}

void main() {

immutable(int)* wah;
void wahwah(immutable(int*) x) {
wah = x;
}
auto c = new immutable(C)(10);
wahwah(c.foo); // why is this privilegied with inout
c.bar(&wahwah); // and this not?

writeln(*wah);

}

Can't use void delegate(const(int*)) there.


Thanks for clarifying, I didn't quite understand the usage before.

This is a limitation of inout's design. Technically inout requires a
single inout output, and can have multiple inout inputs. Your example
matches that description, so in theory it's possible.


I realized last night that this won't work. Simple reason -- during an
inout function, the function promises to treat the arguments as if they
were const.

If your class instance was mutable, this would not be true, e.g.:

class C
{
int x;
void bar(void delegate(inout(int)* f) inout { f(&x); }
}

void main() {

auto c = new C;
void dg(int *f) {*f = 10;}
c.bar(&dg); // modifies c, even though the function is marked as inout
}

-Steve


Well, inout was conceived as a counter to where you need to write the 
exact same function for every type of constness, was it not? :-)


Re: Generic collection/element function signatures in D2 versus D1

2010-09-08 Thread Steven Schveighoffer
On Tue, 07 Sep 2010 14:06:58 -0400, Steven Schveighoffer  
 wrote:


On Tue, 07 Sep 2010 11:37:20 -0400, Pelle   
wrote:



On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:

Yes, a valid return. Your function should be:

void foo(void delegate(const(C) f) const

It helps to understand that inout/const/immutable has NOTHING to do  
with
code generation, it only has to do with limiting what compiles. For  
this

reason, an inout function is compiled once, and works on all three
constancies (4 if you have a nested inout function). For the entire
function any inout variable is treated as a non-changeable value, just
like const. Then when you return, it's converted at the call site back
to the constancy with which it was called. If the return value is void,
then there's nothing to convert, and no reason to use inout over const.

I'll repeat -- there is no benefit to inout if you are not returning
anything.

-Steve


That's not an equivalent function signature. Or maybe it is, but look  
at this (sorry it's so long):


class C {
 int x;
 this(int y) { x = y; }

 inout(int*) foo() inout {
 return &x;
 }
 void bar(void delegate(int*) f) {
 f(&x);
 }
 void bar(void delegate(const(int*)) f) const {
 f(&x);
 }
 void bar(void delegate(immutable(int*)) f) immutable {
 f(&x);
 }
}

void main() {

 immutable(int)* wah;
 void wahwah(immutable(int*) x) {
 wah = x;
 }
 auto c = new immutable(C)(10);
 wahwah(c.foo);  // why is this privilegied with inout
 c.bar(&wahwah); // and this not?

 writeln(*wah);

}

Can't use void delegate(const(int*)) there.


Thanks for clarifying, I didn't quite understand the usage before.

This is a limitation of inout's design.  Technically inout requires a  
single inout output, and can have multiple inout inputs.  Your example  
matches that description, so in theory it's possible.


I realized last night that this won't work.  Simple reason -- during an  
inout function, the function promises to treat the arguments as if they  
were const.


If your class instance was mutable, this would not be true, e.g.:

class C
{
   int x;
   void bar(void delegate(inout(int)* f) inout { f(&x); }
}

void main() {

   auto c = new C;
   void dg(int *f) {*f = 10;}
   c.bar(&dg); // modifies c, even though the function is marked as inout
}

-Steve


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Jacob Carlborg

On 2010-09-07 17:37, Pelle wrote:

On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:

Yes, a valid return. Your function should be:

void foo(void delegate(const(C) f) const

It helps to understand that inout/const/immutable has NOTHING to do with
code generation, it only has to do with limiting what compiles. For this
reason, an inout function is compiled once, and works on all three
constancies (4 if you have a nested inout function). For the entire
function any inout variable is treated as a non-changeable value, just
like const. Then when you return, it's converted at the call site back
to the constancy with which it was called. If the return value is void,
then there's nothing to convert, and no reason to use inout over const.

I'll repeat -- there is no benefit to inout if you are not returning
anything.

-Steve


That's not an equivalent function signature. Or maybe it is, but look at
this (sorry it's so long):

class C {
int x;
this(int y) { x = y; }

inout(int*) foo() inout {
return &x;
}
void bar(void delegate(int*) f) {
f(&x);
}
void bar(void delegate(const(int*)) f) const {
f(&x);
}
void bar(void delegate(immutable(int*)) f) immutable {
f(&x);
}
}

void main() {

immutable(int)* wah;
void wahwah(immutable(int*) x) {
wah = x;
}
auto c = new immutable(C)(10);
wahwah(c.foo); // why is this privilegied with inout
c.bar(&wahwah); // and this not?

writeln(*wah);

}

Can't use void delegate(const(int*)) there.


That won't work, you can't have inout on return of a function without 
having inout for a least one parameter. The compiler can't know what to 
resolve inout to, mutable, immutable or const.


--
/Jacob Carlborg


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Steven Schveighoffer

On Tue, 07 Sep 2010 11:37:20 -0400, Pelle  wrote:


On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:

Yes, a valid return. Your function should be:

void foo(void delegate(const(C) f) const

It helps to understand that inout/const/immutable has NOTHING to do with
code generation, it only has to do with limiting what compiles. For this
reason, an inout function is compiled once, and works on all three
constancies (4 if you have a nested inout function). For the entire
function any inout variable is treated as a non-changeable value, just
like const. Then when you return, it's converted at the call site back
to the constancy with which it was called. If the return value is void,
then there's nothing to convert, and no reason to use inout over const.

I'll repeat -- there is no benefit to inout if you are not returning
anything.

-Steve


That's not an equivalent function signature. Or maybe it is, but look at  
this (sorry it's so long):


class C {
 int x;
 this(int y) { x = y; }

 inout(int*) foo() inout {
 return &x;
 }
 void bar(void delegate(int*) f) {
 f(&x);
 }
 void bar(void delegate(const(int*)) f) const {
 f(&x);
 }
 void bar(void delegate(immutable(int*)) f) immutable {
 f(&x);
 }
}

void main() {

 immutable(int)* wah;
 void wahwah(immutable(int*) x) {
 wah = x;
 }
 auto c = new immutable(C)(10);
 wahwah(c.foo);  // why is this privilegied with inout
 c.bar(&wahwah); // and this not?

 writeln(*wah);

}

Can't use void delegate(const(int*)) there.


Thanks for clarifying, I didn't quite understand the usage before.

This is a limitation of inout's design.  Technically inout requires a  
single inout output, and can have multiple inout inputs.  Your example  
matches that description, so in theory it's possible.


But to simplify things, a function's only inout output must be on the  
return value.  So things like void fn(inout int* x, out inout(int) y)  
don't qualify either.


IMO there is a whole host of implicit delegate casting that should be  
possible, but isn't, including delegate contravariance.  However, let's  
get inout working as it's currently designed before we go relaxing the  
requirements.  I'm not a compiler/language designer, so I'm unsure if what  
you want has any pitfalls.


-Steve


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Pelle

On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:

Yes, a valid return. Your function should be:

void foo(void delegate(const(C) f) const

It helps to understand that inout/const/immutable has NOTHING to do with
code generation, it only has to do with limiting what compiles. For this
reason, an inout function is compiled once, and works on all three
constancies (4 if you have a nested inout function). For the entire
function any inout variable is treated as a non-changeable value, just
like const. Then when you return, it's converted at the call site back
to the constancy with which it was called. If the return value is void,
then there's nothing to convert, and no reason to use inout over const.

I'll repeat -- there is no benefit to inout if you are not returning
anything.

-Steve


That's not an equivalent function signature. Or maybe it is, but look at 
this (sorry it's so long):


class C {
int x;
this(int y) { x = y; }

inout(int*) foo() inout {
return &x;
}
void bar(void delegate(int*) f) {
f(&x);
}
void bar(void delegate(const(int*)) f) const {
f(&x);
}
void bar(void delegate(immutable(int*)) f) immutable {
f(&x);
}
}

void main() {

immutable(int)* wah;
void wahwah(immutable(int*) x) {
wah = x;
}
auto c = new immutable(C)(10);
wahwah(c.foo);  // why is this privilegied with inout
c.bar(&wahwah); // and this not?

writeln(*wah);

}

Can't use void delegate(const(int*)) there.


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Steven Schveighoffer

On Tue, 07 Sep 2010 09:28:18 -0400, Pelle  wrote:


On 09/07/2010 03:15 PM, Steven Schveighoffer wrote:

On Tue, 07 Sep 2010 08:56:15 -0400, Jacob Carlborg  wrote:


On 2010-09-07 14:49, Steven Schveighoffer wrote:

On Sun, 05 Sep 2010 09:40:59 -0400, BLS  wrote:


On 05/09/2010 02:16, Jonathan M Davis wrote:

void foo(T)(T[] collection, T elem)

{
// Blah, whatever
}



I am curious, how this will look and feel once inout is working ?

inout void foo(T)(inout(T)[] collection, inout T elem)
{
// Blah, whatever}
}



inout void doesn't make any sense. You can't have a const void or
immutable void.

Now, if foo is a member function, then inout applies to the "this"
pointer, but even then, you need a return type other than void for  
inout

to be used.

-Steve


inout is only used when you want to return the same constness
(mutable, const, immutable) as you passed in to the function. If you
don't want that, or don't want to return anything then const(T)[] is
what you want. It will accept mutable, const and immutable.


Yes, exactly. This is why inout functions cannot return void.

-Steve


Hmm.

class C {
 void foo(void delegate(inout(C)) f) inout {
 f(this);
 }
}

Am I missing something?


Yes, a valid return.  Your function should be:

void foo(void delegate(const(C) f) const

It helps to understand that inout/const/immutable has NOTHING to do with  
code generation, it only has to do with limiting what compiles.  For this  
reason, an inout function is compiled once, and works on all three  
constancies (4 if you have a nested inout function).  For the entire  
function any inout variable is treated as a non-changeable value, just  
like const.  Then when you return, it's converted at the call site back to  
the constancy with which it was called.  If the return value is void, then  
there's nothing to convert, and no reason to use inout over const.


I'll repeat -- there is no benefit to inout if you are not returning  
anything.


-Steve


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Pelle

On 09/07/2010 03:15 PM, Steven Schveighoffer wrote:

On Tue, 07 Sep 2010 08:56:15 -0400, Jacob Carlborg  wrote:


On 2010-09-07 14:49, Steven Schveighoffer wrote:

On Sun, 05 Sep 2010 09:40:59 -0400, BLS  wrote:


On 05/09/2010 02:16, Jonathan M Davis wrote:

void foo(T)(T[] collection, T elem)

{
// Blah, whatever
}



I am curious, how this will look and feel once inout is working ?

inout void foo(T)(inout(T)[] collection, inout T elem)
{
// Blah, whatever}
}



inout void doesn't make any sense. You can't have a const void or
immutable void.

Now, if foo is a member function, then inout applies to the "this"
pointer, but even then, you need a return type other than void for inout
to be used.

-Steve


inout is only used when you want to return the same constness
(mutable, const, immutable) as you passed in to the function. If you
don't want that, or don't want to return anything then const(T)[] is
what you want. It will accept mutable, const and immutable.


Yes, exactly. This is why inout functions cannot return void.

-Steve


Hmm.

class C {
void foo(void delegate(inout(C)) f) inout {
f(this);
}
}

Am I missing something?


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Steven Schveighoffer

On Tue, 07 Sep 2010 08:56:15 -0400, Jacob Carlborg  wrote:


On 2010-09-07 14:49, Steven Schveighoffer wrote:

On Sun, 05 Sep 2010 09:40:59 -0400, BLS  wrote:


On 05/09/2010 02:16, Jonathan M Davis wrote:

void foo(T)(T[] collection, T elem)

{
// Blah, whatever
}



I am curious, how this will look and feel once inout is working ?

inout void foo(T)(inout(T)[] collection, inout T elem)
{
// Blah, whatever}
}



inout void doesn't make any sense. You can't have a const void or
immutable void.

Now, if foo is a member function, then inout applies to the "this"
pointer, but even then, you need a return type other than void for inout
to be used.

-Steve


inout is only used when you want to return the same constness (mutable,  
const, immutable) as you passed in to the function. If you don't want  
that, or don't want to return anything then const(T)[] is what you want.  
It will accept mutable, const and immutable.


Yes, exactly.  This is why inout functions cannot return void.

-Steve


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Jacob Carlborg

On 2010-09-07 14:49, Steven Schveighoffer wrote:

On Sun, 05 Sep 2010 09:40:59 -0400, BLS  wrote:


On 05/09/2010 02:16, Jonathan M Davis wrote:

void foo(T)(T[] collection, T elem)

{
// Blah, whatever
}



I am curious, how this will look and feel once inout is working ?

inout void foo(T)(inout(T)[] collection, inout T elem)
{
// Blah, whatever}
}



inout void doesn't make any sense. You can't have a const void or
immutable void.

Now, if foo is a member function, then inout applies to the "this"
pointer, but even then, you need a return type other than void for inout
to be used.

-Steve


inout is only used when you want to return the same constness (mutable, 
const, immutable) as you passed in to the function. If you don't want 
that, or don't want to return anything then const(T)[] is what you want. 
It will accept mutable, const and immutable.


--
/Jacob Carlborg


Re: Generic collection/element function signatures in D2 versus D1

2010-09-07 Thread Steven Schveighoffer

On Sun, 05 Sep 2010 09:40:59 -0400, BLS  wrote:


On 05/09/2010 02:16, Jonathan M Davis wrote:

void foo(T)(T[] collection, T elem)

 {
  // Blah, whatever
 }



I am curious, how this will look and feel once inout is working ?

inout void foo(T)(inout(T)[] collection, inout T elem)
{
   // Blah, whatever}
}



inout void doesn't make any sense.  You can't have a const void or  
immutable void.


Now, if foo is a member function, then inout applies to the "this"  
pointer, but even then, you need a return type other than void for inout  
to be used.


-Steve


Re: Generic collection/element function signatures in D2 versus D1

2010-09-05 Thread BLS

On 05/09/2010 02:16, Jonathan M Davis wrote:

void foo(T)(T[] collection, T elem)

 {
  // Blah, whatever
 }



I am curious, how this will look and feel once inout is working ?

inout void foo(T)(inout(T)[] collection, inout T elem)
{
  // Blah, whatever}
}



Re: Generic collection/element function signatures in D2 versus D1

2010-09-04 Thread Jonathan M Davis
On Saturday 04 September 2010 00:57:48 Nick Sabalausky wrote:
> In D1 I did this sort of thing a fair amount:
> 
> void foo(T)(T[] collection, T elem)
> {
> // Blah, whatever
> }
> 
> Worked for any of the string types, worked for any array, or anything with
> the appropriate opIndexes, and for all I know there may be some improvement
> that could still be made. But of course, in D2 strings have that extra
> immutable part that mucks up the above for strings (and then there's
> ranges), so: Is there a typical generally-best way in D2 to declare a
> function signature for operating on collections and elements? I know it
> would involve using the standard range interfaces in the body and choosing
> the most restrictive range type that gets the job done, and I'm fine with
> all that, but is there a good example of a typical "best-practice"
> generic-function signature in D2?
> 
> ---
> Not sent from an iPhone.

Okay, here's a shot at it:

import std.algorithm;
import std.array;
import std.container;
import std.stdio;
import std.traits;

void foo(T, U)(T collection, U elem)
if(is(U : Unqual!(typeof(collection[].front
{
if(elem == collection.front)
writefln("%s == %s", elem, collection.front);
else
writefln("%s != %s", elem, collection.front);
}

void bar(R, U)(R range, U elem)
if(is(U : Unqual!(typeof(range.front
{
if(elem == range.front)
writefln("%s == %s", elem, range.front);
else
writefln("%s != %s", elem, range.front);
}

void main()
{
dstring a = "hello world";
foo(a, 'h');
foo(a, 'g');
bar(a, 'h');
bar(a, 'g');

writeln();
Array!int b;
b.insert(1);
b.insert(2);
b.insert(3);

foo(b, 1);
foo(b, 2);
bar(b, 1);
bar(b, 2);

writeln();
SList!int c;
c.insert(3);
c.insert(2);
c.insert(1);

foo(c, 1);
foo(c, 2);
bar(c, 1);
bar(c, 2);

writeln();
auto d = find(c[], 2);

bar(d, 1);
bar(d, 2);
}


foo() takes a container type where you can get a range to the whole thing with 
a 
slice, and bar() works on ranges. However, it looks like all of the containers 
in std.container currently implement front(), so both foo() and bar() work on 
them. Of course, if you doing stuff that isn't on a range, then bar() wouldn't 
work, and foo() won't work on ranges. So, which you want probably depends on 
what you're trying to do. A function like bar will work on more but will be 
restricted to range-base operations only. And depending on what you do in a 
function like bar(), you might need more template constraints to constrain the 
type of range.

I haven't tried any of this with CTFE, but the function signatures should work 
just fine with it. Whether you can use CTFE should therefore be a question of 
what you try to do in the function.

In any case, I think that Unqual is the secret sauce that you're looking for 
here.

- Jonathan M Davis


Re: Generic collection/element function signatures in D2 versus D1

2010-09-04 Thread Jacob Carlborg

On 2010-09-04 10:02, Nick Sabalausky wrote:

"Nick Sabalausky"  wrote in message
news:i5su5e$23m...@digitalmars.com...

In D1 I did this sort of thing a fair amount:

void foo(T)(T[] collection, T elem)
{
// Blah, whatever
}

Worked for any of the string types, worked for any array, or anything with
the appropriate opIndexes, and for all I know there may be some
improvement that could still be made. But of course, in D2 strings have
that extra immutable part that mucks up the above for strings (and then
there's ranges), so: Is there a typical generally-best way in D2 to
declare a function signature for operating on collections and elements? I
know it would involve using the standard range interfaces in the body and
choosing the most restrictive range type that gets the job done, and I'm
fine with all that, but is there a good example of a typical
"best-practice" generic-function signature in D2?



Oh, also, and perhaps more importantly (I forgot, this was my main original
reason for even posting the question):

What would be the *right* D2 version of the above code that *didn't* bother
with ranges, and just stuck with arrays and strings? Sometimes I need to do
something in CTFE and using ranges leads to using "std.algorithm", and CTFE
still tends to choke on a lot of "std.algorithm".


If you're not going to modify the content of the array I think this will 
work:


void foo (T) (const(T)[] collection, T elem) {}

This will allow both mutable, immutable and const arrays. But it will 
not let you modify the array like this:


collection[3] = 'a';


--
/Jacob Carlborg


Re: Generic collection/element function signatures in D2 versus D1

2010-09-04 Thread Nick Sabalausky
"Nick Sabalausky"  wrote in message 
news:i5su5e$23m...@digitalmars.com...
> In D1 I did this sort of thing a fair amount:
>
> void foo(T)(T[] collection, T elem)
> {
>// Blah, whatever
> }
>
> Worked for any of the string types, worked for any array, or anything with 
> the appropriate opIndexes, and for all I know there may be some 
> improvement that could still be made. But of course, in D2 strings have 
> that extra immutable part that mucks up the above for strings (and then 
> there's ranges), so: Is there a typical generally-best way in D2 to 
> declare a function signature for operating on collections and elements? I 
> know it would involve using the standard range interfaces in the body and 
> choosing the most restrictive range type that gets the job done, and I'm 
> fine with all that, but is there a good example of a typical 
> "best-practice" generic-function signature in D2?
>

Oh, also, and perhaps more importantly (I forgot, this was my main original 
reason for even posting the question):

What would be the *right* D2 version of the above code that *didn't* bother 
with ranges, and just stuck with arrays and strings? Sometimes I need to do 
something in CTFE and using ranges leads to using "std.algorithm", and CTFE 
still tends to choke on a lot of "std.algorithm".




Generic collection/element function signatures in D2 versus D1

2010-09-04 Thread Nick Sabalausky
In D1 I did this sort of thing a fair amount:

void foo(T)(T[] collection, T elem)
{
// Blah, whatever
}

Worked for any of the string types, worked for any array, or anything with 
the appropriate opIndexes, and for all I know there may be some improvement 
that could still be made. But of course, in D2 strings have that extra 
immutable part that mucks up the above for strings (and then there's 
ranges), so: Is there a typical generally-best way in D2 to declare a 
function signature for operating on collections and elements? I know it 
would involve using the standard range interfaces in the body and choosing 
the most restrictive range type that gets the job done, and I'm fine with 
all that, but is there a good example of a typical "best-practice" 
generic-function signature in D2?

---
Not sent from an iPhone.