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
Extending or implementing Function should be legal #7780
Comments
I think this is actually the most reasonable behavior. There is no good reason to implement Function. I'd prefer this to be fixed in the spec rather than in the implementations (but the language group are ofcourse free to disagree). Added Area-Language, Triaged labels. |
This comment was originally written by @a14n Thanks for your answer. For instance in the following example I simulate varargs : typedef dynamic OnCall(List); Here the Editor puts a warning '"VarargsFunction" is not a function type' on "superHeroes(...)". |
The problem is that it is not a function. Even if you implement Function, you don't implement any actual function type. Example: I can see that using Function.apply, which is functionality not otherwise available, is hard to do in checked mode, even when using otherwise unchecked variables. We could probably change it to not require a Function, but then I fear it will mask other real errors. On the other hand, making it possible to extend/implement Function is pretty safe. It only breaks something for objects that do so but aren't functions, and they're asking for it. So, I can see the problem. I'm not yet convinced that a cure is worth its side-effects. Added Accepted label. |
Preventing the implementation (or subclassing) of Function is not supported by the spec. It is true that implementing it a pure documentation gesture. I don't see any reason to change the spec however. |
Whether it's implementing Function, so that noSuchMethod can be used to catch call() invocations, or it's some other method of allowing the creation of a function that can be used with any invocation, this would be really useful for framework developers, testing, and other cases where generic wrappers for functions are needed. We could get rid of all the expectAsyncX() methods in unittest for example. Added C1 label. |
This comment was originally written by avix...@gmail.com This feature is extremely important for enabling the FP style in Dart. Without it implementing any generic function decorator is impossible in the checked mode. The partial function is one example of such a decorator: func(pos1, pos2) => "$pos1 $pos2"; The only way to implement it right now is the following: partial(Function func, List args) => new PartiallyAppliedFunction(func, args); class PartiallyAppliedFunction { PartiallyAppliedFunction(this.func, this.posArgs); noSuchMethod(Invocation c) => c.memberName == s("call") ? _applyFunction(c) : super.noSuchMethod(c); _applyFunction(Invocation c){ The problem here is that an instance of PartiallyAppliedFunction is not a function, which means that: expect(_.partial(func, ["pos1"]) is Function, equals(false)); Obviously, the partial function is not the only example. Another one: var funcWhereArgsMustBePresent = ensureArgsArePresent(func); |
Just to be totally clear: Implementing Function has always been allowed by the spec. Any class that implements call is a subtype of Function. In fact, it is a subtype of the function type F, where F is the function type of its call method. See section 15.5 of the spec. If this is not working, then the implementation has a bug and it should be fixed. |
This comment was originally written by avix10...@gmail.com I didn't know that, but implementing call fixes the issue with "is Function" not being true. It is a little bit awkward, cause you have to implement both call and noSuchMethod. class PartiallyAppliedFunction { PartiallyAppliedFunction(this.func, this.posArgs); call() => Function.apply(func, posArgs); _applyFunction(Invocation c){ but it is not a big deal. However, it looks like checks against typedefs still don't work. |
Any update on this? I have a case currently where we're deciding on a typedef or single-method interface for an API. I'd like to use the typedef, and it's great that a class can "implement" the typedef via call(), but one of the arguments for the interface is that the interface allows documentation via the implements clause, where a typedef doesn't. I'm still surprised that this isn't legal: typedef T Formatter<T>(LogRecord record); class MyFormatter implements Formatter<String> { |
The intent here seems to have morphed a bit over time. I believe the current request is to be able to treat function types as interfaces so that they can be use in implements clauses. This has some benefits for documentation and typechecking. However, mixing function types with interfaces has some issues. Today interfaces are only derived from classes. A function type is not a class, and we don't necessarily want people to be able to extend them etc. Set owner to @gbracha. |
This comment was originally written by @chalin Btw, this issue (at least the original topic of this issue), has been resolved: a class can extend or implement Function, and a static warning is issued if it does so without defining call() or noSuchMethod(). Hence this issue should probably be closed with a new issue open to track the new request. |
This issue was originally filed by @a14n
According to Gilad Bracha in https://groups.google.com/a/dartlang.org/d/msg/misc/U7HGNg9UYGU/_qERSLxjyJcJ , it should be legal to extend or implement Function.
However, in Dart Editor 0.2.10_r16761 I get errors
- "'Function' can not be used as superclass" when I try to extend Function
- "'Function' can not be used as superinterface" when I try to implement Function.
The same kind of error appears when I try to launch in dartium or compile with dart2js.
The text was updated successfully, but these errors were encountered: