Sdk: Is Dart a stupid language or I'm not getting it properly (Functions as 1st-class objects)

Created on 23 May 2020  路  3Comments  路  Source: dart-lang/sdk

Hello Everyone,

Functions as first-class objects

```
void printElements(int x) {
print(x);
}
var mylist = [1, 2, 3];
print(mylist.runtimeType);
mylist.forEach(printElements);


Output: List`<int>` 1 2 3 
(works perfectly fine)

**Problem occurs when i change var to List** 
  ```
List mylist = <int>[1, 2, 3];
  print(mylist.runtimeType); //runtimeType is still the same List<int>
  mylist.forEach(printElements); //now this statement is giving Error.

Error: The function 'printElements' has type 'void Function(int)' that isn't of expected type 'void Function(dynamic)'. This means its parameter or return type doesn't match what is expected

I don't know why this statement is giving error when the runtimeType is same in both the cases.

Thanks and regards,
Amit Verma

type-question

Most helpful comment

The implicit dynamic is known to be a sharp edge to the language, and predates some of the inference ideas (it certainly seems logical that if var a = [1, 2, 3] has an inferred static type of List<int>, then List a = [1, 2, 3] would have an inferred static type of List<int> as well). There are some analysis options that can help out:

In analysis_options.yaml you can specify:

analyzer:
 language:
   strict-raw-types: true

I think also the linter rule: always_specify_types will warn you.

All 3 comments

Dart has a static type system, so every variable has a static type, that is known by the compiler.
Every object also has a runtimeType, which is the actual type of this object at runtime, and this may be a more specific type.

What you are doing here is basically this:

class Animal{}
class Cat extends Animal{
  void meow(){}
}
void main(){
   Animal animal = Cat();
   print(animal.runtimeType); // prints Cat
   animal.meow(); // fails, because the static type of animal is Animal, not cat
}

By writing

List mylist = <int>[1, 2, 3];

The static type of mylist is set to List<dynamic>.
Even if the type of the right-hand side would be inferred toList<int>, you specify the type explicitly, which overwrites the type inference. Just List without generic type parameter is shorthand for List<dynamic>, which is a more general type than List<int>.

But your function

void printElements(int x) {
  print(x);
}

can only take parameters of type int, not type dynamic! So because the static type of your variable is List<dynamic>, the function passed to forEach must have a signature of void Function(dynamic) but it has a signature of void Function(int).

You can fix this error either by specifying the correct type of the variable:
List<int> mylist = <int>[1, 2, 3];

or by letting the compiler figure out the correct type by itself:

var mylist = <int>[1, 2, 3];

@knaeckeKami Thanks a ton for explaining so deeply. Sorry i am still new in my dart-flutter journey. So, i was't aware of this thing..
Thanks again..
Amit

The implicit dynamic is known to be a sharp edge to the language, and predates some of the inference ideas (it certainly seems logical that if var a = [1, 2, 3] has an inferred static type of List<int>, then List a = [1, 2, 3] would have an inferred static type of List<int> as well). There are some analysis options that can help out:

In analysis_options.yaml you can specify:

analyzer:
 language:
   strict-raw-types: true

I think also the linter rule: always_specify_types will warn you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DartBot picture DartBot  路  3Comments

matanlurey picture matanlurey  路  3Comments

brooth picture brooth  路  3Comments

nex3 picture nex3  路  3Comments

55555Mohit55555 picture 55555Mohit55555  路  3Comments