Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

abstract @:to conversion is not triggered within boolean operation #6893

Open
nadako opened this issue Mar 7, 2018 · 5 comments
Open

abstract @:to conversion is not triggered within boolean operation #6893

nadako opened this issue Mar 7, 2018 · 5 comments

Comments

@nadako
Copy link
Member

nadako commented Mar 7, 2018

abstract A(Int) from Int to Int {
  @:to function toBool() return this != 0;
}

class Test {
  static function main() {
    var i:A = 1;
    i && false; // A should be Bool
    !i; // A should be Bool
    if (i) trace(""); // works
  }
}```
@bendmorris
Copy link
Contributor

This seems reasonable to me, && and ! are just operations. There"s no requirement that their terms are bools, or that they return bools:

abstract A(String) from String to String {
    @:op(A && B) public static function and(a:A, b:A):A {
        return (a == "true" && b == "true") ? "true" : "false";
    }

    @:op(!A) public static function neg(a:A):A {
        return a == "true" ? "false" : "true";
    }
}

class Test {
    static function main() {
        var a:A = "true";
        var b:A = "false";
        trace(a && a);
        trace(a && b);
        trace(!a);
        trace(!b);
    }
}

(And OTOH there is a requirement that an if condition is a bool, so the whole expression is coerced to one.)

I"m using this in one case to overload || for a custom type as syntactic sugar.

@RealyUniqueName
Copy link
Member

I thought it"s a specified behaviour. Unless you define operators overloading for an abstract, you can"t use that abstract with those operators.

@RealyUniqueName
Copy link
Member

RealyUniqueName commented Mar 7, 2018

abstract A(Int) from Int to Int {
  @:to function toBool() return this != 0;
  @:op(A && B) function andBool(b:Bool) return toBool() != b;
}

class Test {
  static function main() {
    var i:A = 1;
    i && true; // Should this evaluate to `true` or to `false`?
  }
}

@nadako
Copy link
Member Author

nadako commented Mar 7, 2018

If there"s no @:op overloads involved, &&, || and ! should be boolean logic ops, right? So it makes sense to try coercing operands to bool and trigger abstracts casts.

If there are @:op overloads, we should of course use those, so @RealyUniqueName"s example should evaluate to false ((1 != 0) != true).

@ousado
Copy link
Contributor

ousado commented Mar 12, 2018

@nadako has a point here - in all other positions where exactly one type is expected, the conversions are triggered - so why not with operators that aren"t overloaded themselves? They"re just like unary or binary functions with infix notation in those cases.
It gets more tricky when the operator is already overloaded, like + - should toInt, toFloat, toString be triggered there? One can argue that these operators aren"t just like functions, because we don"t have function overloading, and hence the same rules can"t apply. So the question is: should all operators be treated specially in that they don"t trigger conversions (like now), or should there be certain criteria when to trigger, e.g. whether the respective operator is "natively" overloaded, or should all operators trigger conversions, and how would that be specified?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants