You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In Python, any instance method is really a static method with a self parameter, and the object you call the method on is implicitly passed first to this method. For example:
classUser:
def__init__(self, name): self.name=namedefsay_hello(self): print(f"Hello, I am {self.name}. How are you?")
alice=User("Alice")
bob=User("Bob")
alice.say_hello()
User.say_hello(alice)
users= [alice, bob]
greetings=map(User.say_hello, users)
In Dart, we often like to use tear-offs instead of passing closures around. A useful example is the following:
classUser {
staticStringmakeGreeting(User user) =>"Hello, I am ${user.name}. How are you?";
finalString name;
User(this.name);
}
voidmain() {
final users = [User("Alice"), User("Bob")];
final greetings = users.map(User.makeGreeting);
}
However, it is no longer possible to pass a tear-off if we make the greeting an instance method:
classUser {
finalString name;
User(this.name);
StringmakeGreeting() =>"Hello, I am $name. How are you?";
}
voidmain() {
final users = [User("Alice"), User("Bob")];
final greetings = users.map((user) => user.makeGreeting());
}
My feature request is to implicitly (or on-demand) make available a static method that's equivalent to the Python version of every instance method. Not advocating for instance methods to be replaced by static methods. But, if there's an instance method named A.b(), then there should be a static method A.$b(A a), and it should be possible to refer to it as just A.b as syntax sugar. In other words:
classUser {
// implicitly generatedstaticString$makeGreeting(User user) => user.makeGreeting();
finalString name;
User(this.name);
StringmakeGreeting() =>"Hello, I am $name. How are you?";
}
voidmain() {
final users = [User("Alice"), User("Bob")];
// translated to User.$makeGreetingfinal greetings = users.map(User.makeGreeting);
}
The semantics seem to be well-defined as far as I can tell. The alias of User.makeGreeting for User.$makeGreeting is safe because there cannot be a static member with the same name as an existing instance member, and using an instance member without an instance is always an error. In other words, the alias strictly adds functionality and doesn't break any existing code or create conflicts. Additionally, the compiler may only decide to generate these if they're directly referenced in the first place. This would allow us to use tear-offs way more frequently, especially in JSON contexts where (obj) => obj.toJson() is quite common.
Edit: One specific case has been pointed out to me where this could cause a conflict:
classClassName {
voidmethodName() { }
}
ClassNamegenerateInstance() =>ClassName();
voidmain() {
final instance =generateInstance();
finalClassName= instance;
ClassName.methodName(); // refers to the instance method
}
In cases like these, where ClassName.methodName is already a valid identifier and would thus cause a conflict, I would say to not generate the implicit static wrapper, to avoid breaking existing code and causing "magic" behavior. But I'm open to whatever makes more sense on a case-by-case basis as well.
The text was updated successfully, but these errors were encountered:
It won't work if we allow static and instance members with the same name in the same class.
Correct, this proposal kind of hinges on that: ClassName.methodName is always a shorthand for the corresponding instance method name and is therefore reserved. It's not breaking currently, but it does restrict future possibilities. I think this is a good use for it, as it would be pretty confusing if ClassName.methodName was too different than instance.methodName
Not sure how well it works for methods with parameters, though.
I left them out intentionally because they certainly do complicate things. In general, you'd probably be safe if you said "let the instance be the first positional parameter, just like Python's self". But I'm indifferent to it, because the main purpose of this proposal is to allow for more convenient tear-offs, and you're unlikely to get a useful tear-off out of this -- unless you specifically have a closure of the form (a, b) => a.method(b),
In Python, any instance method is really a static method with a
self
parameter, and the object you call the method on is implicitly passed first to this method. For example:In Dart, we often like to use tear-offs instead of passing closures around. A useful example is the following:
However, it is no longer possible to pass a tear-off if we make the greeting an instance method:
My feature request is to implicitly (or on-demand) make available a static method that's equivalent to the Python version of every instance method. Not advocating for instance methods to be replaced by static methods. But, if there's an instance method named
A.b()
, then there should be a static methodA.$b(A a)
, and it should be possible to refer to it as justA.b
as syntax sugar. In other words:The semantics seem to be well-defined as far as I can tell. The alias of
User.makeGreeting
forUser.$makeGreeting
is safe because there cannot be a static member with the same name as an existing instance member, and using an instance member without an instance is always an error. In other words, the alias strictly adds functionality and doesn't break any existing code or create conflicts. Additionally, the compiler may only decide to generate these if they're directly referenced in the first place. This would allow us to use tear-offs way more frequently, especially in JSON contexts where(obj) => obj.toJson()
is quite common.Edit: One specific case has been pointed out to me where this could cause a conflict:
In cases like these, where
ClassName.methodName
is already a valid identifier and would thus cause a conflict, I would say to not generate the implicit static wrapper, to avoid breaking existing code and causing "magic" behavior. But I'm open to whatever makes more sense on a case-by-case basis as well.The text was updated successfully, but these errors were encountered: