Skip to content

Support for defining a new operator #607

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

Open
elliottdehn opened this issue Oct 7, 2019 · 2 comments
Open

Support for defining a new operator #607

elliottdehn opened this issue Oct 7, 2019 · 2 comments
Labels
request Requests to resolve a particular developer problem

Comments

@elliottdehn
Copy link

Dart supports operator overloading which is cool, however, often times it can be desired to define new operators (perhaps ones you are familiar with from another language) to perform certain common tasks (for you) on certain types in a highly fluent manner.

@lrhn lrhn added the request Requests to resolve a particular developer problem label Oct 7, 2019
@lrhn
Copy link
Member

lrhn commented Oct 7, 2019

This would mean being able to introduce new syntax.

Dart currently only recognizes a certain number of prefix, infix and suffix operators, and you can only provide new meaning for those. That has the advantage that the parser not depending on the program being parsed. It seems unlikely that we will allow code to introduce completely new operators which the scanner and parser must then recognize (say a @-@ b). We would still have to assign a finite number of characters to be available for these operators, so you cannot use characters that are already meaningful in Dart, like {, }, (, ), =, . or ,.
It would also have to not conflict with existing syntax so x +- 2 would not be possible because it already means x + (-2). We would at least have to change tokenization enough that +- becomes one token and + - becomes two. Then I guess it would be technically possible to treat x +/- y as the +/- operator called on x with y, and treat it like any other method name. We'd consider any combination of the currently overridable operator characters as an operator name (and the operator is a setter if the name ends in =).

Then there is precedence. We have fixed precedence of the existing operators, but I'd prefer not to allow you to define a new precedence for new operators. That would make syntax parsing depend on already having understood the declaration, which is bad. We could perhaps assign a precedence corresponding to the longest operator which is a prefix of the new operator name, so +/- has the precedence of + and >>>> has the same precedence (and restrictions) as >>>.
The alternative is to always pick a specific precedence for unknown/custom operators, which will likely force a lot of extra parentheses (Kotlin's infix functions have this issue).

In either case, that would be a significant change. I find it more likely that we'll introduce special syntax for method names that are not plain ASCII, and then allow that for operators as well. Say:

abstract class Boolish {
  bool get isTrue;
  T `if`<T>(T ifTrue, T ifFalse) => this.isTrue ? ifTrue : ifFalse;
  Boolish operator `and`(Boolish also) => this.isTrue ? also : this; // Binary because parameter.
  Boolish operator `or`(Boolish orElse) => this.isTrue ? this : orElse;
  Boolish operator `not`() => this.isTrue ? BoolBoolish.false : BoolBoolish.true; // Prefix.
}
/// usable as:
main() {
  Boolish b = IntegerBoolish(1);
  assert(b.if(42, 37) == 42);
  assert(b `and` b == b);
  assert(b `or` b == b);
  assert((`not` b).if(false, true));
}

(This is basically Kotlin infix functions, but only usable as infix, and still with the precedence issues forcing lots of extra parentheses).

@elliottdehn
Copy link
Author

I like this, but you are right. It would be a large change, and for something that could possibly be argued as an anti-pattern. Thanks for the response!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

2 participants