Re: why won't byPair work with a const AA?

2017-08-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/3/17 4:30 AM, Olivier FAURE wrote:

I understand the general concept you're describing, but what exactly are 
tail modifiers? It's the first time I see this name, and my google-fu 
gives me nothing.


tail modifiers are modifiers that only apply to the "tail" of the type.

For example const(int)* is applying const to the "tail" of the int 
pointer, that is, the int that it points at. It's not applying to the 
actual pointer itself (we call that the "head").


Another way to look at it is that when you copy a variable you always 
make a copy of the head, and you don't make a copy of the tail. For this 
reason, the fully-modified and tail-modified types are implicitly 
castable, and this is the important property we need to duplicate.


A tail-modified struct would be something like this:

struct S
{
   int * x;
}

const(S) s;

This looks like this:

struct ConstS
{
   const(int *) x;
}

A tail-const S would look like this:

struct TailConstS
{
   const(int)* x;
}

That is, everything the struct points at remains const, but the actual 
data of the struct is now mutable.


Note that TailConstS and ConstS can implicitly convert.

This is how arrays work. An array T[] is really:

struct Array
{
   size_t length;
   T* ptr;
}

A tail-const array const(T)[] is really:

struct TailConstArray
{
   size_t length; // mutable
   const(T)* ptr; // mutable, but points at const data
}

This property of implicit casting is what's needed to fully realize 
custom ranges and const together. The way to get it is to define 
tail-modifier syntax for all types, not just arrays and pointers.


-Steve


Re: why won't byPair work with a const AA?

2017-08-03 Thread Olivier FAURE via Digitalmars-d-learn

On Wednesday, 2 August 2017 at 18:06:03 UTC, H. S. Teoh wrote:
On Wed, Aug 02, 2017 at 01:15:44PM -0400, Steven Schveighoffer 
via Digitalmars-d-learn wrote: [...]
The real answer is to have tail modifiers for structs, so you 
can do the same thing an array does. Note that if Result is an 
array, you CAN use inout:


auto byPair(AA)(inout(AA) aa)
{
   alias Result = inout(X)[];
   return Result(...);
}

[...]

Yeah, this isn't the first time I've run into this.  But then 
the problem becomes, how do you design tail modifiers for 
structs?


I understand the general concept you're describing, but what 
exactly are tail modifiers? It's the first time I see this name, 
and my google-fu gives me nothing.


Re: why won't byPair work with a const AA?

2017-08-02 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Aug 02, 2017 at 11:06:03AM -0700, H. S. Teoh via Digitalmars-d-learn 
wrote:
[...]
>   auto byPair(AA)(inout(AA) aa)
>   {
>   alias Modifiers = std.traits.getModifiers!AA;
>   struct Result {
>   std.traits.ApplyModifiers!(Slot*, Modifiers) slot;
>   ... // range methods here
>   }
>   return Result(aa);
>   }
> 
> Of course, getModifiers and ApplyModifiers are fictitious Phobos
> templates, but you get the idea.
[...]

Hmm, actually, they don't have to be fictitious; here's an actual,
compilable example:

struct Slot {
Slot* next;
string key;
int value;
}
struct AA {
Slot*[] slots;
}
auto byPair(AA)(AA aa)
{
import std.traits : QualifierOf;
alias Qual = QualifierOf!AA;
struct Result {
Qual!(Slot)* slot;
bool empty() { return slot is null; }
auto front() {
struct Front {
Qual!string key;
Qual!int value;
}
return Front(slot.key, slot.value);
}
void popFront() {
slot = slot.next;
}
}
return Result(aa.slots[0]);
}
unittest {
AA aa;
const(AA) constAa;
immutable(AA) immAa;

auto mutPair = aa.byPair;
static assert(is(typeof(mutPair.front.value) == int));

auto constPair = constAa.byPair;
static assert(is(typeof(constPair.front.value) == const(int)));

auto immPair = immAa.byPair;
static assert(is(typeof(immPair.front.value) == 
immutable(int)));
}


T

-- 
If Java had true garbage collection, most programs would delete themselves upon 
execution. -- Robert Sewell


Re: why won't byPair work with a const AA?

2017-08-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/2/17 2:06 PM, H. S. Teoh via Digitalmars-d-learn wrote:

On Wed, Aug 02, 2017 at 01:15:44PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
[...]

It's not currently legal, you can't have inout members of a struct.
This could be added, but it still wouldn't work, because you can't
"strip off" the inout part upon return.

The real answer is to have tail modifiers for structs, so you can do
the same thing an array does. Note that if Result is an array, you CAN
use inout:

auto byPair(AA)(inout(AA) aa)
{
alias Result = inout(X)[];
return Result(...);
}

[...]

Yeah, this isn't the first time I've run into this.  But then the
problem becomes, how do you design tail modifiers for structs?


I have ideas :) I just haven't fleshed them out enough to present the 
case. I've told Andrei about them and his reaction was not positive. But 
I think eventually D will need them.



Because
here the inout (or its equivalent) has to apply to one specific member;
the range methods can't also inherit the modifier otherwise in the const
case you wouldn't be able to implement popFront().

I suppose, within the current type system, you'd have to template on
modifiers, as you said, so that the incoming modifier is properly
represented in the resulting type.  But since we're already templating
on the AA type, perhaps what we could do is something like:

auto byPair(AA)(inout(AA) aa)
{
alias Modifiers = std.traits.getModifiers!AA;
struct Result {
std.traits.ApplyModifiers!(Slot*, Modifiers) slot;
... // range methods here
}
return Result(aa);
}

Of course, getModifiers and ApplyModifiers are fictitious Phobos
templates, but you get the idea.


Yes, but of course inout doesn't play a role here, as it's not a 
compile-time construct. Just:


auto byPair(AA)(AA aa)

-Steve


Re: why won't byPair work with a const AA?

2017-08-02 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Aug 02, 2017 at 01:15:44PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
[...]
> It's not currently legal, you can't have inout members of a struct.
> This could be added, but it still wouldn't work, because you can't
> "strip off" the inout part upon return.
> 
> The real answer is to have tail modifiers for structs, so you can do
> the same thing an array does. Note that if Result is an array, you CAN
> use inout:
> 
> auto byPair(AA)(inout(AA) aa)
> {
>alias Result = inout(X)[];
>return Result(...);
> }
[...]

Yeah, this isn't the first time I've run into this.  But then the
problem becomes, how do you design tail modifiers for structs?  Because
here the inout (or its equivalent) has to apply to one specific member;
the range methods can't also inherit the modifier otherwise in the const
case you wouldn't be able to implement popFront().

I suppose, within the current type system, you'd have to template on
modifiers, as you said, so that the incoming modifier is properly
represented in the resulting type.  But since we're already templating
on the AA type, perhaps what we could do is something like:

auto byPair(AA)(inout(AA) aa)
{
alias Modifiers = std.traits.getModifiers!AA;
struct Result {
std.traits.ApplyModifiers!(Slot*, Modifiers) slot;
... // range methods here
}
return Result(aa);
}

Of course, getModifiers and ApplyModifiers are fictitious Phobos
templates, but you get the idea.


T

-- 
Дерево держится корнями, а человек - друзьями.


Re: why won't byPair work with a const AA?

2017-08-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/2/17 11:52 AM, H. S. Teoh via Digitalmars-d-learn wrote:

On Wed, Aug 02, 2017 at 08:20:23AM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:

On 8/1/17 7:44 PM, H. S. Teoh via Digitalmars-d-learn wrote:

[...]

You can iterate a const AA, but if you want to iterate a non-const AA,
you need a different type.

For instance, if your AA is int*[string], you will get const(int*) out
of it, which may not be what you want.

Unless your range is a slice or a pointer, then you can't do it
properly without having separate types for const, immutable, mutable
ranges. You can use templates to build them, but it's not
straightforward or pleasant.

[...]

Hmm. This seems like a perfect use case for inout, though I'm not
confident the current implementation of inout can handle this. You'd do
something like this:

auto byPair(AA)(inout(AA) aa)
{
struct Result
{
inout(Slot)* current;
... // range primitives here
}
return Result(aa);
}

What I'm unsure of is whether the current implementation of inout can
handle the inout inside the definition of Result.


It's not currently legal, you can't have inout members of a struct. This 
could be added, but it still wouldn't work, because you can't "strip 
off" the inout part upon return.


The real answer is to have tail modifiers for structs, so you can do the 
same thing an array does. Note that if Result is an array, you CAN use 
inout:


auto byPair(AA)(inout(AA) aa)
{
   alias Result = inout(X)[];
   return Result(...);
}

-Steve


Re: why won't byPair work with a const AA?

2017-08-02 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Aug 02, 2017 at 08:20:23AM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On 8/1/17 7:44 PM, H. S. Teoh via Digitalmars-d-learn wrote:
[...]
> You can iterate a const AA, but if you want to iterate a non-const AA,
> you need a different type.
> 
> For instance, if your AA is int*[string], you will get const(int*) out
> of it, which may not be what you want.
> 
> Unless your range is a slice or a pointer, then you can't do it
> properly without having separate types for const, immutable, mutable
> ranges. You can use templates to build them, but it's not
> straightforward or pleasant.
[...]

Hmm. This seems like a perfect use case for inout, though I'm not
confident the current implementation of inout can handle this. You'd do
something like this:

auto byPair(AA)(inout(AA) aa)
{
struct Result
{
inout(Slot)* current;
... // range primitives here
}
return Result(aa);
}

What I'm unsure of is whether the current implementation of inout can
handle the inout inside the definition of Result.


T

-- 
Trying to define yourself is like trying to bite your own teeth. -- Alan Watts


Re: why won't byPair work with a const AA?

2017-08-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/1/17 7:44 PM, H. S. Teoh via Digitalmars-d-learn wrote:

On Tue, Aug 01, 2017 at 07:31:41PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:

On 8/1/17 7:15 PM, H. S. Teoh via Digitalmars-d-learn wrote:

On Tue, Aug 01, 2017 at 07:09:45PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:

If this were a true implementation without the opaqueness, it
would not work properly.

[...]

Actually, a proper implementation would still work, provided you
declare your pointer types carefully.  Sketch of idea:

auto byKeyValue(AA)(AA aa) {
struct Result {
const(Slot)* current; // N.B.: proper type
bool empty() { ... }
auto front() { return Pair(*current); }
void popFront() {
current = current.next;
...
}
}
return Result(aa);
}

Basically, the type of `current` must be const(Slot)* rather than
const(Slot*), which would be the default inferred type. But since
it's legal to assign a const pointer to a pointer to const (you
can't modify the original pointer, nor what it points to, but it's
valid to copy the pointer to a mutable pointer variable, as long as
what is pointed to is still const), this actually will work without
breaking / bypassing the type system.


No, you can't const the Slot, because if the value type is a pointer,
you can't then cast away the const-ness of it legally.

There are ways to get it right, it involves templating for mutability.

[...]

Counter-proof:

struct Slot {
Slot* next;
const(string) key;
const(int) value;
}
struct AA {
Slot*[] slots;
}
unittest {
const(AA) aa;

static assert(is(typeof(aa.slots[0]) == const(Slot*)));
const(Slot)* p = aa.slots[0];   // N.B.: legal
p = p.next; // N.B.: legal
}

Note especially the type checked for in the static assert: you cannot
modify any of the Slot pointers in the AA, but you *can* assign them to
mutable (but tail-const) pointers. Therefore you totally can iterate a
const AA without any casts or any breaking of the type system. And
there's no need to template for mutability either.


You can iterate a const AA, but if you want to iterate a non-const AA, 
you need a different type.


For instance, if your AA is int*[string], you will get const(int*) out 
of it, which may not be what you want.


Unless your range is a slice or a pointer, then you can't do it properly 
without having separate types for const, immutable, mutable ranges. You 
can use templates to build them, but it's not straightforward or pleasant.


-Steve


Re: why won't byPair work with a const AA?

2017-08-01 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Aug 01, 2017 at 07:31:41PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On 8/1/17 7:15 PM, H. S. Teoh via Digitalmars-d-learn wrote:
> > On Tue, Aug 01, 2017 at 07:09:45PM -0400, Steven Schveighoffer via 
> > Digitalmars-d-learn wrote:
> > > If this were a true implementation without the opaqueness, it
> > > would not work properly.
> > [...]
> > 
> > Actually, a proper implementation would still work, provided you
> > declare your pointer types carefully.  Sketch of idea:
> > 
> > auto byKeyValue(AA)(AA aa) {
> > struct Result {
> > const(Slot)* current; // N.B.: proper type
> > bool empty() { ... }
> > auto front() { return Pair(*current); }
> > void popFront() {
> > current = current.next;
> > ...
> > }
> > }
> > return Result(aa);
> > }
> > 
> > Basically, the type of `current` must be const(Slot)* rather than
> > const(Slot*), which would be the default inferred type. But since
> > it's legal to assign a const pointer to a pointer to const (you
> > can't modify the original pointer, nor what it points to, but it's
> > valid to copy the pointer to a mutable pointer variable, as long as
> > what is pointed to is still const), this actually will work without
> > breaking / bypassing the type system.
> 
> No, you can't const the Slot, because if the value type is a pointer,
> you can't then cast away the const-ness of it legally.
> 
> There are ways to get it right, it involves templating for mutability.
[...]

Counter-proof:

struct Slot {
Slot* next;
const(string) key;
const(int) value;
}
struct AA {
Slot*[] slots;
}
unittest {
const(AA) aa;

static assert(is(typeof(aa.slots[0]) == const(Slot*)));
const(Slot)* p = aa.slots[0];   // N.B.: legal
p = p.next; // N.B.: legal
}

Note especially the type checked for in the static assert: you cannot
modify any of the Slot pointers in the AA, but you *can* assign them to
mutable (but tail-const) pointers. Therefore you totally can iterate a
const AA without any casts or any breaking of the type system. And
there's no need to template for mutability either.


T

-- 
One Word to write them all, One Access to find them, One Excel to count them 
all, And thus to Windows bind them. -- Mike Champion


Re: why won't byPair work with a const AA?

2017-08-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/1/17 7:15 PM, H. S. Teoh via Digitalmars-d-learn wrote:

On Tue, Aug 01, 2017 at 07:09:45PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:

If this were a true implementation without the opaqueness, it would
not work properly.

[...]

Actually, a proper implementation would still work, provided you declare
your pointer types carefully.  Sketch of idea:

auto byKeyValue(AA)(AA aa) {
struct Result {
const(Slot)* current; // N.B.: proper type
bool empty() { ... }
auto front() { return Pair(*current); }
void popFront() {
current = current.next;
...
}
}
return Result(aa);
}

Basically, the type of `current` must be const(Slot)* rather than
const(Slot*), which would be the default inferred type. But since it's
legal to assign a const pointer to a pointer to const (you can't modify
the original pointer, nor what it points to, but it's valid to copy the
pointer to a mutable pointer variable, as long as what is pointed to is
still const), this actually will work without breaking / bypassing the
type system.


No, you can't const the Slot, because if the value type is a pointer, 
you can't then cast away the const-ness of it legally.


There are ways to get it right, it involves templating for mutability.

The current code is pretty horrific though, any way you slice it.

-Steve


Re: why won't byPair work with a const AA?

2017-08-01 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Aug 01, 2017 at 07:09:45PM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On 8/1/17 6:50 PM, H. S. Teoh via Digitalmars-d-learn wrote:
[...]
> > Actually, there's nothing about the implementation of both
> > byKeyValue (the underlying implementation in druntime) and byPair in
> > std.array that would preclude them from being used with const AA's.
> > The only flaw is that the declaration of byPair doesn't match const
> > AA's:
> > 
> > https://issues.dlang.org/show_bug.cgi?id=17711
> > 
> > Here's the fix:
> > 
> > https://github.com/dlang/phobos/pull/5668
> 
> It works, because the byKeyValue implementation is so... ugly.
> 
> For instance this:
> 
> return Result(_aaRange(cast(void*)aa));
> 
> Just throws away all const/mutability. However, the Pair struct inside
> restores the correct modifiers. I hope...
> 
> If this were a true implementation without the opaqueness, it would
> not work properly.
[...]

Actually, a proper implementation would still work, provided you declare
your pointer types carefully.  Sketch of idea:

auto byKeyValue(AA)(AA aa) {
struct Result {
const(Slot)* current; // N.B.: proper type
bool empty() { ... }
auto front() { return Pair(*current); }
void popFront() {
current = current.next;
...
}
}
return Result(aa);
}

Basically, the type of `current` must be const(Slot)* rather than
const(Slot*), which would be the default inferred type. But since it's
legal to assign a const pointer to a pointer to const (you can't modify
the original pointer, nor what it points to, but it's valid to copy the
pointer to a mutable pointer variable, as long as what is pointed to is
still const), this actually will work without breaking / bypassing the
type system.


T

-- 
People tell me that I'm skeptical, but I don't believe them.


Re: why won't byPair work with a const AA?

2017-08-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/1/17 6:50 PM, H. S. Teoh via Digitalmars-d-learn wrote:

On Tue, Aug 01, 2017 at 10:04:18AM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:

On 7/30/17 12:19 AM, Matthew Gamble wrote:

[...]

import std.array;
import std.algorithm;

class A
{
  this() { aa = ["a":1, "b" : 2, "c" : 3]; }
  auto pairs() @property const { return
aa.byPair.array.sort().release; }
private:
  int[string] aa;
}

If I remove const from the pairs function it compiles fine. I'm just
not sure this is a behavior I want. Any help/recommendation would be
appreciated.


byPair must store a pointer to the data in the AA. If you mark the AA
const, then it must store a const pointer to AA data.

[...]

Actually, there's nothing about the implementation of both byKeyValue
(the underlying implementation in druntime) and byPair in std.array that
would preclude them from being used with const AA's.  The only flaw is
that the declaration of byPair doesn't match const AA's:

https://issues.dlang.org/show_bug.cgi?id=17711

Here's the fix:

https://github.com/dlang/phobos/pull/5668


It works, because the byKeyValue implementation is so... ugly.

For instance this:

return Result(_aaRange(cast(void*)aa));

Just throws away all const/mutability. However, the Pair struct inside 
restores the correct modifiers. I hope...


If this were a true implementation without the opaqueness, it would not 
work properly.


-Steve


Re: why won't byPair work with a const AA?

2017-08-01 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Aug 01, 2017 at 10:04:18AM -0400, Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On 7/30/17 12:19 AM, Matthew Gamble wrote:
[...]
> > import std.array;
> > import std.algorithm;
> > 
> > class A
> > {
> >  this() { aa = ["a":1, "b" : 2, "c" : 3]; }
> >  auto pairs() @property const { return
> > aa.byPair.array.sort().release; }
> > private:
> >  int[string] aa;
> > }
> > 
> > If I remove const from the pairs function it compiles fine. I'm just
> > not sure this is a behavior I want. Any help/recommendation would be
> > appreciated.
> 
> byPair must store a pointer to the data in the AA. If you mark the AA
> const, then it must store a const pointer to AA data.
[...]

Actually, there's nothing about the implementation of both byKeyValue
(the underlying implementation in druntime) and byPair in std.array that
would preclude them from being used with const AA's.  The only flaw is
that the declaration of byPair doesn't match const AA's:

https://issues.dlang.org/show_bug.cgi?id=17711

Here's the fix:

https://github.com/dlang/phobos/pull/5668


T

-- 
Sometimes the best solution to morale problems is just to fire all of the 
unhappy people. -- despair.com


Re: why won't byPair work with a const AA?

2017-08-01 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/30/17 12:19 AM, Matthew Gamble wrote:
I have a class member function from which I'm trying to return a sorted 
array of key, value tuples stored in an associative array as a private 
member. The member function should be able to be marked const to prevent 
the AA from being modified. I have reduced the problem to the simple 
case below which won't compile with DMD v2.072.2.


import std.array;
import std.algorithm;

class A
{
 this() { aa = ["a":1, "b" : 2, "c" : 3]; }
 auto pairs() @property const { return 
aa.byPair.array.sort().release; }

private:
 int[string] aa;
}

If I remove const from the pairs function it compiles fine. I'm just not 
sure this is a behavior I want. Any help/recommendation would be 
appreciated.


byPair must store a pointer to the data in the AA. If you mark the AA 
const, then it must store a const pointer to AA data.


However, because we don't have tail modifiers, you can't construct just 
one range that would make this work. We would need many different 
ranges, one for each flavor of mutability.


So you are stuck doing what Ali recommended -- cast away the const.

In this case, no harm comes if you don't cast back to const (since the 
value of the AA is `int`), but in general this solution isn't valid if 
the value type contains references.


-Steve


Re: why won't byPair work with a const AA?

2017-07-29 Thread Ali Çehreli via Digitalmars-d-learn

On 07/29/2017 10:15 PM, Matthew Gamble wrote:

>> I think it should work. I think a cast to unqualified is a safe
>> workaround in this case:
>>
>> auto pairs() @property const { return
>> (cast(int[string])aa).byPair.array.sort().release; }

As your question reveals, casting away const is not safe in general and 
not for this code. :-/


> That works to solve the compile problem. Seems the data in aa was safe
> from modification without the const or casting, even if the values are
> reference types (i.e. ClassB[string]). Is that expected?

No, they are not safe as you can mutate values in the AA:

import std.stdio;
import std.array;
import std.algorithm;

class B {
int i;
void mutate() {
++i;
}
}

class A
{
this() { aa = ["a" : new B(), "b" : new B(), "c" : new B()]; }
auto pairs() @property const { return 
(cast(B[string])aa).byPair.array.sort().release; }

private:
B[string] aa;
}

void main() {
auto a = new A();
auto p = a.pairs();
p.front[1].mutate();
assert(p.front[1].i == 1);// <-- Mutated :(
}

Of course, the problem is the same without const and the cast.

Ali



Re: why won't byPair work with a const AA?

2017-07-29 Thread Matthew Gamble via Digitalmars-d-learn

On Sunday, 30 July 2017 at 04:36:19 UTC, Ali Çehreli wrote:

On 07/29/2017 09:19 PM, Matthew Gamble wrote:
I have a class member function from which I'm trying to return 
a sorted
array of key, value tuples stored in an associative array as a 
private
member. The member function should be able to be marked const 
to prevent
the AA from being modified. I have reduced the problem to the 
simple

case below which won't compile with DMD v2.072.2.

import std.array;
import std.algorithm;

class A
{
this() { aa = ["a":1, "b" : 2, "c" : 3]; }
auto pairs() @property const { return 
aa.byPair.array.sort().release; }

private:
int[string] aa;
}

If I remove const from the pairs function it compiles fine. 
I'm just not
sure this is a behavior I want. Any help/recommendation would 
be

appreciated.


I think it should work. I think a cast to unqualified is a safe 
workaround in this case:


auto pairs() @property const { return 
(cast(int[string])aa).byPair.array.sort().release; }


Ali


Thanks Ali,

That works to solve the compile problem. Seems the data in aa was 
safe from modification without the const or casting, even if the 
values are reference types (i.e. ClassB[string]). Is that 
expected?


Best,
Matt


Re: why won't byPair work with a const AA?

2017-07-29 Thread Ali Çehreli via Digitalmars-d-learn

On 07/29/2017 09:19 PM, Matthew Gamble wrote:

I have a class member function from which I'm trying to return a sorted
array of key, value tuples stored in an associative array as a private
member. The member function should be able to be marked const to prevent
the AA from being modified. I have reduced the problem to the simple
case below which won't compile with DMD v2.072.2.

import std.array;
import std.algorithm;

class A
{
this() { aa = ["a":1, "b" : 2, "c" : 3]; }
auto pairs() @property const { return aa.byPair.array.sort().release; }
private:
int[string] aa;
}

If I remove const from the pairs function it compiles fine. I'm just not
sure this is a behavior I want. Any help/recommendation would be
appreciated.


I think it should work. I think a cast to unqualified is a safe 
workaround in this case:


auto pairs() @property const { return 
(cast(int[string])aa).byPair.array.sort().release; }


Ali



why won't byPair work with a const AA?

2017-07-29 Thread Matthew Gamble via Digitalmars-d-learn
I have a class member function from which I'm trying to return a 
sorted array of key, value tuples stored in an associative array 
as a private member. The member function should be able to be 
marked const to prevent the AA from being modified. I have 
reduced the problem to the simple case below which won't compile 
with DMD v2.072.2.


import std.array;
import std.algorithm;

class A
{
this() { aa = ["a":1, "b" : 2, "c" : 3]; }
	auto pairs() @property const { return 
aa.byPair.array.sort().release; }

private:
int[string] aa;
}

If I remove const from the pairs function it compiles fine. I'm 
just not sure this is a behavior I want. Any help/recommendation 
would be appreciated.