Discussion:
[dart-misc] Dart 2 Breaking Change: Callable Classes
'Leaf Petersen' via Dart Misc
2018-02-21 22:14:08 UTC
Permalink
Hi Dart folks -

We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.

*What is changing?*

In Dart 1, a class with a call method is a subtype of a function type with
the same signature.

```dart
// Dart 1
class C {
void call(int x) {}
}

typedef void F(int i);

void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.

F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```

In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
This changes the behavior of the code snippet above as follows:

```dart
// Dart 2
class C {
void call(int x) {}
}

typedef void F(int i);

void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.

F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```

*What will break?*

Most code that uses call methods is unaffected by this, and will silently
continue to work.

Code that passes off callable objects as functions and then casts them back
to the original class type will no longer work. This is rare, but code
such as this can be refactored either to use the Expando class to attach
the required state to an actual function, or to explicitly manage state
using Maps from the function to associated state.

Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.

*How do I know if this has broken me?*

The most likely error that you will likely see as a result of this change
is a runtime cast failure, with a message that looks like this:

Type '(int) => int' is not a subtype of type 'CallableClass'

This error is indicating that a function typed value is being explicitly or
implicitly cast to `CallableClass`, where `CallableClass` is some class
with a `call` method. Previously, the value being cast would have been an
instance of `CallableClass`, and so the cast would have succeeded. After
this change, the value being cast is the closurization of the `.call`
method from `CallableClass`, and cannot be cast back to the original
object.

*Why is this change being made?*

Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause substantial
implementation complexity. Making uses of callable classes as function
types behave as a closurization of the call method supports the vast
majority of use cases that we have found, at a tiny fraction of the
implementation complexity.

I will update here when this change lands. Please reach out to me here or
offline with any concerns, and/or with help resolving any issues after this
change has landed.

thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Anatoly Pulyaevskiy
2018-02-21 22:39:58 UTC
Permalink
Related question: is implementing Function still considered deprecated in
Dart 2? Will it produce some sort of warning similar to those we get when
attempting to implement other built-in types (class Foo implements String,
for instance)?

On Wed, Feb 21, 2018 at 2:14 PM 'Leaf Petersen' via Dart Misc <
Post by 'Leaf Petersen' via Dart Misc
Hi Dart folks -
We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.
*What is changing?*
In Dart 1, a class with a call method is a subtype of a function type with
the same signature.
```dart
// Dart 1
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.
F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```
In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
```dart
// Dart 2
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.
F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```
*What will break?*
Most code that uses call methods is unaffected by this, and will silently
continue to work.
Code that passes off callable objects as functions and then casts them
back to the original class type will no longer work. This is rare, but
code such as this can be refactored either to use the Expando class to
attach the required state to an actual function, or to explicitly manage
state using Maps from the function to associated state.
Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.
*How do I know if this has broken me?*
The most likely error that you will likely see as a result of this change
Type '(int) => int' is not a subtype of type 'CallableClass'
This error is indicating that a function typed value is being explicitly
or implicitly cast to `CallableClass`, where `CallableClass` is some class
with a `call` method. Previously, the value being cast would have been an
instance of `CallableClass`, and so the cast would have succeeded. After
this change, the value being cast is the closurization of the `.call`
method from `CallableClass`, and cannot be cast back to the original
object.
*Why is this change being made?*
Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause
substantial implementation complexity. Making uses of callable classes as
function types behave as a closurization of the call method supports the
vast majority of use cases that we have found, at a tiny fraction of the
implementation complexity.
I will update here when this change lands. Please reach out to me here or
offline with any concerns, and/or with help resolving any issues after this
change has landed.
thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Erik Ernst' via Dart Misc
2018-02-22 10:11:07 UTC
Permalink
On Wed, Feb 21, 2018 at 11:39 PM, Anatoly Pulyaevskiy <
Post by Anatoly Pulyaevskiy
Related question: is implementing Function still considered deprecated in
Dart 2? Will it produce some sort of warning similar to those we get when
attempting to implement other built-in types (class Foo implements String,
for instance)?
Implementing `Function` has very little value: The static analysis of an
instance of type `Function` is done as if that instance had a method named
`call` for all possible method signatures (so we basically "turn the type
checker off" for such invocations), but the invocation will fail unless the
given instance actually has a method named `call` and it is capable of
accepting the given actual arguments. So it allows certain unsafe actions
to take place.

Conversely, if a class implements a `call` method and does not implement
`Function`, an instance of that type will still get the implicit tear-off
when used in a context where a function type is required, so `implements
Function` will not help "making such instances work like a function".

Dynamically, function invocation will invoke a regular function object
(such as the result of evaluating a function literal like `() => 42`), and
otherwise it will check whether a non-function-object has a method named
`call` and, if so, call that, so `implements Function` again does not help.

All in all, `implements Function` does not provide any other services than
allowing your code to fail in some extra ways. ;-)

So, while `implements Function` is not technically prevented (it is not an
error), it should not be used.

On Wed, Feb 21, 2018 at 2:14 PM 'Leaf Petersen' via Dart Misc <
Post by Anatoly Pulyaevskiy
Post by 'Leaf Petersen' via Dart Misc
Hi Dart folks -
We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.
*What is changing?*
In Dart 1, a class with a call method is a subtype of a function type
with the same signature.
```dart
// Dart 1
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.
F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```
In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
```dart
// Dart 2
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.
F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```
*What will break?*
Most code that uses call methods is unaffected by this, and will silently
continue to work.
Code that passes off callable objects as functions and then casts them
back to the original class type will no longer work. This is rare, but
code such as this can be refactored either to use the Expando class to
attach the required state to an actual function, or to explicitly manage
state using Maps from the function to associated state.
Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.
*How do I know if this has broken me?*
The most likely error that you will likely see as a result of this change
Type '(int) => int' is not a subtype of type 'CallableClass'
This error is indicating that a function typed value is being explicitly
or implicitly cast to `CallableClass`, where `CallableClass` is some class
with a `call` method. Previously, the value being cast would have been an
instance of `CallableClass`, and so the cast would have succeeded. After
this change, the value being cast is the closurization of the `.call`
method from `CallableClass`, and cannot be cast back to the original
object.
*Why is this change being made?*
Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause
substantial implementation complexity. Making uses of callable classes as
function types behave as a closurization of the call method supports the
vast majority of use cases that we have found, at a tiny fraction of the
implementation complexity.
I will update here when this change lands. Please reach out to me here
or offline with any concerns, and/or with help resolving any issues after
this change has landed.
thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
Erik Ernst - Google Danmark ApS
Skt Petri Passage 5, 2 sal, 1165 KÞbenhavn K, Denmark
CVR no. 28866984
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Anatoly Pulyaevskiy
2018-02-23 01:41:12 UTC
Permalink
Thanks for a thorough reply Erik!

Your points make sense to me.

Though I feel like if overall recommendation is "it should not be used"
then maybe we can give a hint to developers about that? A lint rule or
analyzer warning (preferably)?

I have been using it up until recently, until I found a small announcement
that it's been deprecated (which is a bit misleading it looks like).

Obviously it is not a big issue but it seems like it can prevent confusion
and promote better dev practices.

On Thu, Feb 22, 2018 at 2:11 AM 'Erik Ernst' via Dart Misc <
Post by 'Erik Ernst' via Dart Misc
On Wed, Feb 21, 2018 at 11:39 PM, Anatoly Pulyaevskiy <
Post by Anatoly Pulyaevskiy
Related question: is implementing Function still considered deprecated in
Dart 2? Will it produce some sort of warning similar to those we get when
attempting to implement other built-in types (class Foo implements String,
for instance)?
Implementing `Function` has very little value: The static analysis of an
instance of type `Function` is done as if that instance had a method named
`call` for all possible method signatures (so we basically "turn the type
checker off" for such invocations), but the invocation will fail unless the
given instance actually has a method named `call` and it is capable of
accepting the given actual arguments. So it allows certain unsafe actions
to take place.
Conversely, if a class implements a `call` method and does not implement
`Function`, an instance of that type will still get the implicit tear-off
when used in a context where a function type is required, so `implements
Function` will not help "making such instances work like a function".
Dynamically, function invocation will invoke a regular function object
(such as the result of evaluating a function literal like `() => 42`), and
otherwise it will check whether a non-function-object has a method named
`call` and, if so, call that, so `implements Function` again does not help.
All in all, `implements Function` does not provide any other services than
allowing your code to fail in some extra ways. ;-)
So, while `implements Function` is not technically prevented (it is not an
error), it should not be used.
On Wed, Feb 21, 2018 at 2:14 PM 'Leaf Petersen' via Dart Misc <
Post by Anatoly Pulyaevskiy
Post by 'Leaf Petersen' via Dart Misc
Hi Dart folks -
We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.
*What is changing?*
In Dart 1, a class with a call method is a subtype of a function type
with the same signature.
```dart
// Dart 1
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.
F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```
In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
```dart
// Dart 2
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.
F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```
*What will break?*
Most code that uses call methods is unaffected by this, and will
silently continue to work.
Code that passes off callable objects as functions and then casts them
back to the original class type will no longer work. This is rare, but
code such as this can be refactored either to use the Expando class to
attach the required state to an actual function, or to explicitly manage
state using Maps from the function to associated state.
Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.
*How do I know if this has broken me?*
The most likely error that you will likely see as a result of this
Type '(int) => int' is not a subtype of type 'CallableClass'
This error is indicating that a function typed value is being explicitly
or implicitly cast to `CallableClass`, where `CallableClass` is some class
with a `call` method. Previously, the value being cast would have been an
instance of `CallableClass`, and so the cast would have succeeded. After
this change, the value being cast is the closurization of the `.call`
method from `CallableClass`, and cannot be cast back to the original
object.
*Why is this change being made?*
Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause
substantial implementation complexity. Making uses of callable classes as
function types behave as a closurization of the call method supports the
vast majority of use cases that we have found, at a tiny fraction of the
implementation complexity.
I will update here when this change lands. Please reach out to me here
or offline with any concerns, and/or with help resolving any issues after
this change has landed.
thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
Erik Ernst - Google Danmark ApS
Skt Petri Passage 5
<https://maps.google.com/?q=Skt+Petri+Passage+5&entry=gmail&source=g>, 2
sal, 1165 KÞbenhavn K, Denmark
CVR no. 28866984
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Erik Ernst' via Dart Misc
2018-02-26 09:39:14 UTC
Permalink
On Fri, Feb 23, 2018 at 2:41 AM, Anatoly Pulyaevskiy <
Post by Anatoly Pulyaevskiy
Thanks for a thorough reply Erik!
Your points make sense to me.
Though I feel like if overall recommendation is "it should not be used"
then maybe we can give a hint to developers about that? A lint rule or
analyzer warning (preferably)?
I have been using it up until recently, until I found a small announcement
that it's been deprecated (which is a bit misleading it looks like).
Obviously it is not a big issue but it seems like it can prevent confusion
and promote better dev practices.
You're right, it is a potential source of confusion, and back in the days
where it did not matter it was even considered good style to "document"
that the instances of a given class were intended to emulate functions by
adding `implements Function`.

So it's also a matter of breakage: How much code will developers have to
change, just so they don't do `implements Function` on a callable class?

One consideration that may be relevant here is that compilation to
JavaScript can be allowed to let a Dart function compile to a JavaScript
function if the Dart function isn't required to be a full-fledged object
(so the JavaScript function is only the potential value of a variable of
type `Object`, `dynamic`, `void`, and `Function`, and all other variables
can be treated in a simpler/faster way because they will be regular
objects). In that setting, it would be nice if `f is Function` were a
reliable test for being a proper function object, which means that it
wouldn't include instances of "callable classes", and that would again fit
well with the Dart 2 updates to the notion of callable classes.

But that change would definitely break all those `implements Function`
clauses, so we want to discourage that, whether or not there will be some
diagnostic message about it. This discussion might help keep that amount of
breakage down a bit. ;-)

On Thu, Feb 22, 2018 at 2:11 AM 'Erik Ernst' via Dart Misc <
Post by Anatoly Pulyaevskiy
Post by 'Erik Ernst' via Dart Misc
On Wed, Feb 21, 2018 at 11:39 PM, Anatoly Pulyaevskiy <
Post by Anatoly Pulyaevskiy
Related question: is implementing Function still considered deprecated
in Dart 2? Will it produce some sort of warning similar to those we get
when attempting to implement other built-in types (class Foo implements
String, for instance)?
Implementing `Function` has very little value: The static analysis of an
instance of type `Function` is done as if that instance had a method named
`call` for all possible method signatures (so we basically "turn the type
checker off" for such invocations), but the invocation will fail unless the
given instance actually has a method named `call` and it is capable of
accepting the given actual arguments. So it allows certain unsafe actions
to take place.
Conversely, if a class implements a `call` method and does not implement
`Function`, an instance of that type will still get the implicit tear-off
when used in a context where a function type is required, so `implements
Function` will not help "making such instances work like a function".
Dynamically, function invocation will invoke a regular function object
(such as the result of evaluating a function literal like `() => 42`), and
otherwise it will check whether a non-function-object has a method named
`call` and, if so, call that, so `implements Function` again does not help.
All in all, `implements Function` does not provide any other services
than allowing your code to fail in some extra ways. ;-)
So, while `implements Function` is not technically prevented (it is not
an error), it should not be used.
On Wed, Feb 21, 2018 at 2:14 PM 'Leaf Petersen' via Dart Misc <
Post by Anatoly Pulyaevskiy
Post by 'Leaf Petersen' via Dart Misc
Hi Dart folks -
We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.
*What is changing?*
In Dart 1, a class with a call method is a subtype of a function type
with the same signature.
```dart
// Dart 1
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.
F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```
In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
```dart
// Dart 2
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.
F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```
*What will break?*
Most code that uses call methods is unaffected by this, and will
silently continue to work.
Code that passes off callable objects as functions and then casts them
back to the original class type will no longer work. This is rare, but
code such as this can be refactored either to use the Expando class to
attach the required state to an actual function, or to explicitly manage
state using Maps from the function to associated state.
Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.
*How do I know if this has broken me?*
The most likely error that you will likely see as a result of this
Type '(int) => int' is not a subtype of type 'CallableClass'
This error is indicating that a function typed value is being
explicitly or implicitly cast to `CallableClass`, where `CallableClass` is
some class with a `call` method. Previously, the value being cast would
have been an instance of `CallableClass`, and so the cast would have
succeeded. After this change, the value being cast is the closurization of
the `.call` method from `CallableClass`, and cannot be cast back to the
original object.
*Why is this change being made?*
Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause
substantial implementation complexity. Making uses of callable classes as
function types behave as a closurization of the call method supports the
vast majority of use cases that we have found, at a tiny fraction of the
implementation complexity.
I will update here when this change lands. Please reach out to me here
or offline with any concerns, and/or with help resolving any issues after
this change has landed.
thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
Erik Ernst - Google Danmark ApS
Skt Petri Passage 5
<https://maps.google.com/?q=Skt+Petri+Passage+5&entry=gmail&source=g>, 2
sal, 1165 KÞbenhavn K, Denmark
CVR no. 28866984
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
Erik Ernst - Google Danmark ApS
Skt Petri Passage 5, 2 sal, 1165 KÞbenhavn K, Denmark
CVR no. 28866984
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Rob Becker
2018-02-23 23:53:13 UTC
Permalink
Hi Leaf,
Would it be possible to make sure that this new proposal for changes to
callable classes doesn't break https://github.com/Workiva/over_react ? Or
is there a branch or some way for me to test that this doesn't
significantly break code at Workiva?
Post by 'Leaf Petersen' via Dart Misc
Hi Dart folks -
We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.
*What is changing?*
In Dart 1, a class with a call method is a subtype of a function type with
the same signature.
```dart
// Dart 1
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.
F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```
In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
```dart
// Dart 2
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.
F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```
*What will break?*
Most code that uses call methods is unaffected by this, and will silently
continue to work.
Code that passes off callable objects as functions and then casts them
back to the original class type will no longer work. This is rare, but
code such as this can be refactored either to use the Expando class to
attach the required state to an actual function, or to explicitly manage
state using Maps from the function to associated state.
Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.
*How do I know if this has broken me?*
The most likely error that you will likely see as a result of this change
Type '(int) => int' is not a subtype of type 'CallableClass'
This error is indicating that a function typed value is being explicitly
or implicitly cast to `CallableClass`, where `CallableClass` is some class
with a `call` method. Previously, the value being cast would have been an
instance of `CallableClass`, and so the cast would have succeeded. After
this change, the value being cast is the closurization of the `.call`
method from `CallableClass`, and cannot be cast back to the original
object.
*Why is this change being made?*
Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause
substantial implementation complexity. Making uses of callable classes as
function types behave as a closurization of the call method supports the
vast majority of use cases that we have found, at a tiny fraction of the
implementation complexity.
I will update here when this change lands. Please reach out to me here or
offline with any concerns, and/or with help resolving any issues after this
change has landed.
thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Leaf Petersen' via Dart Misc
2018-02-26 20:37:36 UTC
Permalink
Rob - What's the best way for us test this? Would us pulling down that
repo and running tests against our prototype give enough coverage?
Otherwise we can look at getting you a branch to test.

-leaf
Post by Rob Becker
Hi Leaf,
Would it be possible to make sure that this new proposal for changes to
callable classes doesn't break https://github.com/Workiva/over_react ? Or
is there a branch or some way for me to test that this doesn't
significantly break code at Workiva?
Post by 'Leaf Petersen' via Dart Misc
Hi Dart folks -
We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.
*What is changing?*
In Dart 1, a class with a call method is a subtype of a function type
with the same signature.
```dart
// Dart 1
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.
F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```
In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
```dart
// Dart 2
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.
F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```
*What will break?*
Most code that uses call methods is unaffected by this, and will silently
continue to work.
Code that passes off callable objects as functions and then casts them
back to the original class type will no longer work. This is rare, but
code such as this can be refactored either to use the Expando class to
attach the required state to an actual function, or to explicitly manage
state using Maps from the function to associated state.
Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.
*How do I know if this has broken me?*
The most likely error that you will likely see as a result of this change
Type '(int) => int' is not a subtype of type 'CallableClass'
This error is indicating that a function typed value is being explicitly
or implicitly cast to `CallableClass`, where `CallableClass` is some class
with a `call` method. Previously, the value being cast would have been an
instance of `CallableClass`, and so the cast would have succeeded. After
this change, the value being cast is the closurization of the `.call`
method from `CallableClass`, and cannot be cast back to the original
object.
*Why is this change being made?*
Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause
substantial implementation complexity. Making uses of callable classes as
function types behave as a closurization of the call method supports the
vast majority of use cases that we have found, at a tiny fraction of the
implementation complexity.
I will update here when this change lands. Please reach out to me here
or offline with any concerns, and/or with help resolving any issues after
this change has landed.
thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Rob Becker
2018-02-26 21:27:43 UTC
Permalink
Leaf, after discussing it I think the best approach would be to get a
branch or build of the proposal that we could use to test agains some
internal non-public code to assess the potential impact. How would you like
to continue?
Post by 'Leaf Petersen' via Dart Misc
Rob - What's the best way for us test this? Would us pulling down that
repo and running tests against our prototype give enough coverage?
Otherwise we can look at getting you a branch to test.
-leaf
Post by Rob Becker
Hi Leaf,
Would it be possible to make sure that this new proposal for changes to
callable classes doesn't break https://github.com/Workiva/over_react ?
Or is there a branch or some way for me to test that this doesn't
significantly break code at Workiva?
Post by 'Leaf Petersen' via Dart Misc
Hi Dart folks -
We (the Dart team) are preparing to land a breaking change for Dart 2
related to callable classes. Below is a summary of the changes and how
they might impact you. Feel free to follow up here or with me directly
with questions.
*What is changing?*
In Dart 1, a class with a call method is a subtype of a function type
with the same signature.
```dart
// Dart 1
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK
f as C; // OK, cast succeeds
c(3); // OK
print(f is C); // OK, prints true.
F f2 = c;
print(identical(f, c)); // OK, prints true
print(f == c); // OK, prints true
print(identical(f, f2)); // OK, prints true
print(f == f2); // OK, prints true
}
```
In Dart 2, we will continue to allow objects with call methods to be
called, and to be assigned to variables of function type. However, the
assignment of an object with a call method to a function type will now be
treated as an implicit closurization of the `.call` method of the object.
```dart
// Dart 2
class C {
void call(int x) {}
}
typedef void F(int i);
void main() {
C c = new C<int>();
F f = c; // OK, treated as F f = c.call;
f as C; // Cast fails
c(3); // OK
print(f is C); // OK, prints false.
F f2 = c;
print(identical(f, c)); // OK, prints false
print(f == c); // OK, prints false
print(identical(f, f2)); // OK, prints true or false
print(f == f2); // OK, prints true
}
```
*What will break?*
Most code that uses call methods is unaffected by this, and will
silently continue to work.
Code that passes off callable objects as functions and then casts them
back to the original class type will no longer work. This is rare, but
code such as this can be refactored either to use the Expando class to
attach the required state to an actual function, or to explicitly manage
state using Maps from the function to associated state.
Code that relies on a callable object being identical to the result of
implicitly casting the callable object to a function type will no longer
work. This is rare, but code that relies on this will need to be
refactored.
*How do I know if this has broken me?*
The most likely error that you will likely see as a result of this
Type '(int) => int' is not a subtype of type 'CallableClass'
This error is indicating that a function typed value is being explicitly
or implicitly cast to `CallableClass`, where `CallableClass` is some class
with a `call` method. Previously, the value being cast would have been an
instance of `CallableClass`, and so the cast would have succeeded. After
this change, the value being cast is the closurization of the `.call`
method from `CallableClass`, and cannot be cast back to the original
object.
*Why is this change being made?*
Callable classes cause complexity in the type system (e.g.
https://github.com/dart-lang/sdk/issues/29791), and also cause
substantial implementation complexity. Making uses of callable classes as
function types behave as a closurization of the call method supports the
vast majority of use cases that we have found, at a tiny fraction of the
implementation complexity.
I will update here when this change lands. Please reach out to me here
or offline with any concerns, and/or with help resolving any issues after
this change has landed.
thanks,
-leaf
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Loading...