Is this a bug or my mistake? [Abstracts operator overloading]

67 views
Skip to first unread message

Alex Kolpakov

unread,
Jun 22, 2015, 4:54:55 AM6/22/15
to haxe...@googlegroups.com
It's stated in the Haxe manuals that it's possible to define behavior like (A - B) and (B - A) where A is the abstract and B is, let's say, Int.
Yet no matter what combination of defining the overloading methods, it always fails as the overloading methods cannot access any fields of the abstract.

Here's the abstract together with the underlying type:

@:forward()
abstract Resource(AResource)
{
inline public function new(i:Int = 0, name:String = "unnamed")
{
this = new AResource();
this.amount = i;
this.name = name;
}
@:to
function toInt():Int
{
return this.amount;
}
@:op(A - B)
function substract(num:Int):Resource
{
var newResource = new Resource();
newResource.amount = this.amount - num;
newResource.name = this.name;
newResource.minAmount = this.minAmount;
newResource.maxAmount = this.maxAmount;
return newResource;
}
@:op(A - B)
static inline function substractRight(num:Int, originalValue:Resource):Resource
{
var newResource = new Resource();
newResource.amount = num - originalValue.amount;
newResource.name = originalValue.name;
newResource.minAmount = originalValue.minAmount;
newResource.maxAmount = originalValue.maxAmount;
return newResource;
}

}

class AResource
{
public var amount(default, set):Int = 0;
public var name:String = "Unnamed";
public var minAmount(default, set):Int = 0;
public var maxAmount(default, set):Int = 999999999;

public function new()
{
}
// GETTERS AND SETTERS
function set_amount(v:Int):Int
{
if (v < minAmount)
return amount = minAmount;
if (v > maxAmount)
return amount = maxAmount;
return amount = v;
}
function set_minAmount(v:Int):Int
{
if (v < minAmount)
return amount = minAmount;
return minAmount = v;
}
function set_maxAmount(v:Int):Int
{
if (v > maxAmount)
return amount = maxAmount;
return maxAmount = v;
}
}

And surely enough if you try:

var r:Resource = new Resource(10, "Silver");
trace(r - 5); // 5

 everything works. Unlike if you try:

var r:Resource = new Resource(10, "Silver");
trace(5 - r); // ERROR: Invalid field access : amount

Is that a bug or am I just making some kind of a mistake? 

Emilio Shodi

unread,
Jul 1, 2015, 1:34:12 AM7/1/15
to haxe...@googlegroups.com
I think @:commutative will help.

понедельник, 22 июня 2015 г., 11:54:55 UTC+3 пользователь Alex Kolpakov написал:

Alex Kolpakov

unread,
Jul 1, 2015, 3:19:18 AM7/1/15
to haxe...@googlegroups.com
 @:commutative won't help on non-commutative operations, otherwise you'll get something like this: 1 / 2 == 2 / 1 
And as you can imagine that could lead to some fuzzy, fuzzy math :D

Emilio Shodi

unread,
Jul 1, 2015, 11:21:27 AM7/1/15
to haxe...@googlegroups.com
Damn you, brain. Of course, substraction is not commutative.
Actually i am total noob in this whole abstract system. I really shoulf find some time to take a closer look at it.

For me, it works like this (Although you losing name and min/max amount this way— any ideas how to save them?)

@:to
function toInt():Int {
return this.amount;
}
@:from
static function fromInt( a:Int ):Resource {
return new Resource( a );
}
@:op(A - B)
static function substractLeft(originalValue:Resource, num:Int):Resource {
var newResource = new Resource();
newResource.amount = originalValue.amount - num;
newResource.name = originalValue.name;
newResource.minAmount = originalValue.minAmount;
newResource.maxAmount = originalValue.maxAmount;
return newResource;
}
@:op(B - A)
static inline function substractRight(num:Int, originalValue:Resource):Resource {
var newResource = new Resource();
newResource.amount = num - originalValue.amount;
newResource.name = originalValue.name;
newResource.minAmount = originalValue.minAmount;
newResource.maxAmount = originalValue.maxAmount;
return newResource;
}

Also, i think there's a mistake in set_minAmount and set_maxAmount

среда, 1 июля 2015 г., 10:19:18 UTC+3 пользователь Alex Kolpakov написал:
Reply all
Reply to author
Forward
0 new messages