Alexey Orlov
Alexey Orlov

Reputation: 2814

Dart: a closure study

This snippet is of no practical significance. I've been just getting used to the closure idea.

var cls = () {
  var x = 5;
  return {
    'x': x,
    'inc': () {x++;},
  };
} ();

void main() {
  print(cls['x']);
  print(cls['inc']);
  cls['inc']();
  print(cls['x']);
}

DartPad output:

5
Closure '_closure'
5
Error compiling to JavaScript:
main.dart:18:13:
Error: The method 'call' isn't defined for the class 'dart.core::Object'.

The desired output would have been something like

5
6

What'd be the cleanest approach to this kind of exercise?

UPD:

The working example, courtesy of Günter Zöchbauer:

var cls = () {
  var x = 5;
  var map = <String, dynamic>{
    'x': x,
  };
  map['inc'] = () {map['x']++;};
  return map;
} ();

void main() {
  print(cls['x']);
  print(cls['inc']);
  cls['inc']();
  print(cls['x']);
}

DartPad output:

5
Closure '_closure'
6

Upvotes: 3

Views: 2465

Answers (2)

Xavier
Xavier

Reputation: 4015

You have to declare the 'x' entry as a Function.

In your code, you set 'x' to the value of the 'x' variable (5) when you return the map. The value will always be 5 and will not update.

var cls = () {
  var x = 5;
  return {
    'x': () => x,
    'inc': () {x++;},
  };
}();

void main() {
  print(cls['x']()); // 5
  print(cls['x']); // Closure: () => int
  print(cls['inc']); // Closure: () => Null
  cls['inc']();
  print(cls['x']()); // 6
}

Upvotes: 4

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657781

var x = 5;
var cls = () {
  return {
    'x': x,
    'inc': () {x++;},
  };
} ();

You would need to move out the variable declaration, otherwise you'd re-declare and re-initialize it to 5 at every call.

update

var cls = () {
  var x = 5;
  var map = {
    'x': x,
   // 'inc': () {map['val']++;}, // not possible to reference the `map` variable that is just declared here so we need to move this out
  };
  map['inc'] = () {map['x']++;};
} ();

Upvotes: 2

Related Questions