# Records and Destructuring — Dart

Source: https://www.skillbyai.com/en/dart/m-records

> Group values with records and unpack them with destructuring.

## Lightweight anonymous data

**Records** (Dart 3) are anonymous, immutable aggregates of values, ideal for returning several values from a function without defining a class. They can have **positional** fields (`(String, int)`, accessed as `$1`, `$2`) and **named** fields (`({String name, int age})`, accessed by name), or both. Records have **structural equality**: two records with the same shape and equal values are `==`, and their `hashCode` matches, so they work as map keys. Their type is part of the signature: `(double lat, double lng) location()`. **Destructuring** unpacks records and other values with patterns: `final (lat, lng) = location();` or `final (:name, :age) = person;` (the `:name` shorthand binds a variable with the field's name). Records pair naturally with `for` loops over `indexed` or map `entries`. Use records for small, local groupings; once a group of values gets a name, behaviour or is used widely, promote it to a class.

## A record as a labelled bundle

A record bundles a few values together without declaring a class, and destructuring unpacks them.

![A small parcel with two or three tagged compartments, and arrows splitting the parcel into separate labelled items.](assets/figures/dart/section-5-map.svg) — Figure 5.1 — Creating and destructuring a record.

## Returning and destructuring records

Several return values without a helper class.

```dart
(double min, double max, double average) stats(List<double> values) {
  final sum = values.fold<double>(0, (a, b) => a + b);
  final sorted = values.toList()..sort();
  return (sorted.first, sorted.last, sum / values.length);
}

({String city, int pinCode}) parseAddress(String text) {
  final parts = text.split(',');
  return (city: parts[0].trim(), pinCode: int.parse(parts[1].trim()));
}

void main() {
  final (min, max, avg) = stats([72, 45, 90, 38]);
  print('min $min, max $max, avg $avg');           // min 38.0, max 90.0, avg 61.25

  final (:city, :pinCode) = parseAddress('Pune, 411001');
  print('$city $pinCode');

  final a = (x: 1, y: 2);
  final b = (x: 1, y: 2);
  print(a == b);                                   // true: structural equality

  final scores = {'Asha': 91, 'Ravi': 64};
  for (final MapEntry(:key, :value) in scores.entries) {
    print('$key scored $value');
  }
}
```

## Name fields when meaning is not obvious

`(double, double)` could be latitude and longitude or width and height. Named fields such as `({double lat, double lng})` make call sites self-explanatory at almost no cost.

**Quiz:** How do records compare for equality in Dart?

- [x] Structurally: same shape and equal field values means equal
- [ ] By identity only
- [ ] They cannot be compared
- [ ] Only by their first field

*Answer:* Structurally: same shape and equal field values means equal. Records have structural equality and matching hash codes.
