Thread overview
Can't call opIndex on class property
Apr 02, 2006
John C
Apr 04, 2006
Aho H. Ullman
Apr 04, 2006
John C
Apr 05, 2006
Aho H. Ullman
April 02, 2006
class NameValue {
    char[][char[]] inner;
    char[] opIndex(char[] name) {
        return inner[name];
    }
    void opIndexAssign(char[] value, char[] name) {
        inner[name] = value;
    }
}

class Client {
    NameValue pairs_;
    this() {
        pairs_ = new NameValue;
    }
    NameValue pairs() {
        return pairs_;
    }
}

void main() {
    Client client = new Client;
    client.pairs["One"] = "Two"; // error here
}

Produces "((client).pairs)()["One"] is not an lvalue".
(Windows XP SP2, DMD 0.150)

Changing the offending line to
    client.pairs()["One"] = "Two"
removes the error, as does this
    client.pairs_["One"] = "Two"
but I'd like to keep it as a property.


April 04, 2006
In article <e0pmst$1ivn$1@digitaldaemon.com>, John C says...
>    NameValue pairs() {
>        return pairs_;
>    }
>but I'd like to keep it as a property.

Properties are defined to be variables or functions, that can be treated as variables, i.e. functions with at most one argument.

You have two arguments and therefore this is not possible in the current version of D.

Maybe resembling the original structure solves your design goal

class Pairs{
void opIndexAssign(char[] value, char[] name) {
pairs_[name] = value;
}
}
Pairs pairs;
this() {
pairs= new Pairs;
}

with the call

client.pairs["One"] = "Two"; // no error here


April 04, 2006
"Aho H. Ullman" <Aho_member@pathlink.com> wrote in message news:e0ukrd$27ub$1@digitaldaemon.com...
> In article <e0pmst$1ivn$1@digitaldaemon.com>, John C says...
>>    NameValue pairs() {
>>        return pairs_;
>>    }
>>but I'd like to keep it as a property.
>
> Properties are defined to be variables or functions, that can be treated
> as
> variables, i.e. functions with at most one argument.
>
> You have two arguments and therefore this is not possible in the current
> version
> of D.

Surely I have no arguments - pairs["Name"] = value should be equivalent to pairs()["Name"] = value.

>
> Maybe resembling the original structure solves your design goal

No, because I want the 'pairs' property to be read-only - that is, users can assign values to names, but not override the internal variable.

>
> class Pairs{
> void opIndexAssign(char[] value, char[] name) {
> pairs_[name] = value;
> }
> }
> Pairs pairs;
> this() {
> pairs= new Pairs;
> }
>
> with the call
>
> client.pairs["One"] = "Two"; // no error here

Wait - didn't I already show in my original post that it works if the variable is used instead?


April 05, 2006
In article <e0uqau$2g5q$1@digitaldaemon.com>, John C says...
>Surely I have no arguments - pairs["Name"] = value should be equivalent to pairs()["Name"] = value.

A property with no arguments is defined to be a getter, so you get the "not an lvalue"-error and are not able to assign. And if you want a setter you have to use one argument, i.e. you are loosing the syntactical appearance of an AA.


>I want the 'pairs' property to be read-only - that is, users can assign values to names, but not override the internal variable.
..
>Wait - didn't I already show in my original post that it works if the variable is used instead?

I haven't clearly expressed what I mean with _resemble_.

I meant to introduce another unprotected variable that implements the protection for the protected internal variable. That unprotected variable is assignable, but the only possible assignment is eliminating every access to the internal variable.

This may solve your primary design goals, but at the cost that every access to the internal variable is sabotageable by a black hat.

---- file "propAA.d"
import std.stdio;
class NameValue {
char[][char[]] inner;
char[] opIndex(char[] name) {
return inner[name];
}
void opIndexAssign(char[] value, char[] name) {
inner[name] = value;
}
}

class Client {
private:
NameValue pairs_;
class Pairs{
void opIndexAssign(char[] value, char[] name) {
pairs_[name] = value;
}
char[] opIndex( char[] name){
return pairs_[ name];
}
}
public:
Pairs pairs;
this() {
pairs_ = new NameValue;
pairs = new Pairs;
}
}

Client client;


------file "user.d"
import propAA;

void main() {
Client client = new Client;
// client.pairs_["One"]="One"; // error: protected
// client.pairs= new Client.Pairs; // at least ineffective
// client.pairs= null; // this sabotages every access
client.pairs["One"] = "Two"; // no error here
writefln( client.pairs["One"]); // assigned
}