• New Horizons on Maelstrom
    Maelstrom New Horizons


    Visit our website www.piratehorizons.com to quickly find download links for the newest versions of our New Horizons mods Beyond New Horizons and Maelstrom New Horizons!

Discussion Is the aref data type guaranteed to be read-only?

Kahenraz

Landlubber
At first I thought that the purpose of the 'aref' data type was to provide a reference to an object's attribute with all the functionality of a traditional reference. But to my surprise I found that assignments to these references had no effect!

It's not possible to use the assignment operator in combination with the reference operator for object attributes:

Code:
object table;
table.num = 123;

// Can't assign a reference to an attribute
aref arNum = &table.num; // error.log: AClass ERROR n1

This seems to be what makearef() is for.

Code:
object table;

table.num = 123;
aref arNum; makearef(arNum, table.num);
table.num = 456;

trace(arNum); // Outputs 456

But here's the interesting part. You can't assign a value to an attribute using an attribute reference. What's even more bizarre is that attempting to do so results in an error "Invalid conversation".

Code:
object table;

table.num = 123;
aref arNum; makearef(arNum, table.num);
table.num = 456;
// Can't assign value to aref?
arNum = 789; // error.log: Invalid conversation

trace(arNum); // Outputs 456

My question here is whether this kind of behavior is guaranteed. Is there any way to assign a value to an attribute using a reference to it or is this impossible?
 
Last edited:
I can't test right now but I think you can modify, but not assign to an aref. So you can only change the attributes properties.

I think this should work:

Code:
object table;

table.num = 123;
aref rTable; makearef(rTable, table);

table.num = 456;
trace(rTable.num); // Outputs 456?

rTable.num= 789;
trace(table.num); // Outputs 789?
 
In your example you're using makearef() on an object at the root node rather than a child attribute. At which point you can simply use '&' or, questionably, 'makeref()' instead:

Code:
ref rTable; makeref(rTable, table);

// or

ref rTable = &table;

Imo, this is an abuse of makearef() as it suggests that the reference points to an attribute when in fact it's pointing to an object.

You are correct though that the reference becomes constant but its attributes are still mutable. This is typical and the behavior is exactly the same even in C.

Code:
object table;

table.child.num = 123;

aref arChild; makearef(arChild, table.child);
trace(arChild.num); // Outputs 123

arChild.num = 456;

trace(table.child.num); // Outputs 456

I've found that '&' and 'makeref()' act like a reference in C whereas 'makearef()' is similar to a const reference. But this is inconsistent because makearef() can't be used on a non-object primitive type to create a const reference.

The confusing nature of the type system used by this language is that there is no dereference operator. Variables that contact a reference (of type ref and aref) are automatically dereferenced on read. A ref type is dereferenced on assignment unless assigning a new reference a aref is dereferenced on read but assignment causes a runtime error. An aref can however be reassigned with another call to 'makearef()'.
 
Last edited:
I was wrong. The target of a ref and aref can be modified using the assignment operator. This changes what the reference is pointing at and is not assigning a value.

Example for ref:

Code:
object table1, table2;
ref rA, rB, rNum;

table1.num = 123;
table2.num = 456;

makeref(rA, table1);
makeref(rB, table2);

// Assign ref by reference not value
rNum = rA;
trace("rNum -> table1 = " + rNum.num); // 123

// Assign ref by reference not value
rNum = rB;
trace("rNum -> table2 = " + rNum.num); // 456

// Confirm that original values remain unchanged
trace("table1.num = " + table1.num); // 123
trace("table2.num = " + table2.num); // 456

Example for aref:

Code:
object table1, table2;
aref arA, arB, arNum;

table1.num = 123;
table2.num = 456;

makearef(arA, table1.num);
makearef(arB, table2.num);

// Assign aref by reference not value
arNum = arA;
trace("arNum -> table1.num = " + arNum); // 123

// Assign aref by reference not value
arNum = arB;
trace("arNum -> table2.num = " + arNum); // 456

// Confirm that original values remain unchanged
trace("table1.num = " + table1.num); // 123
trace("table2.num = " + table2.num); // 456
 
Last edited:
Back
Top