# Functions and Parameters — Dart

Source: https://www.skillbyai.com/en/dart/fn-params

> Write functions with positional, optional, named and required parameters.

## Flexible, readable function signatures

Dart functions have a return type (inferred for local functions), a name and parameters. Parameters come in three kinds. **Required positional** parameters come first: `double area(double w, double h)`. **Optional positional** parameters go in square brackets with defaults: `String greet(String name, [String greeting = 'Hello'])`. **Named** parameters go in braces, are optional unless marked **`required`**, and are passed by name in any order: `void connect({required String host, int port = 443})`, called as `connect(host: 'api.example.com')`. Named parameters dominate Flutter APIs because they make calls with many options readable. Single-expression functions can use **arrow syntax** (`int square(int x) => x * x;`). Functions are **first-class objects**: they can be assigned to variables, passed as arguments and returned. Top-level functions, static methods and instance methods can all be torn off into function values. Use **`void`** for functions that return nothing and `Never` for functions that always throw.

## Kinds of parameters

Required positional parameters first, then either optional positional or named parameters.

![A function box with three groups of input slots: solid slots, bracketed dashed slots and labelled slots with name tags.](assets/figures/dart/section-3-map.svg) — Figure 3.1 — Positional, optional positional and named parameters.

## Parameter styles in practice

Named parameters with required and defaults read clearly at the call site.

```dart
double lineTotal(double unitPrice, int quantity, [double discount = 0]) =>
    unitPrice * quantity * (1 - discount);

String formatPrice(num amount, {String currency = 'INR', int decimals = 2}) =>
    '${amount.toStringAsFixed(decimals)} $currency';

void sendInvoice({required String to, required double amount, bool urgent = false}) {
  print('Sending ${formatPrice(amount)} invoice to $to${urgent ? ' (urgent)' : ''}');
}

void main() {
  print(lineTotal(49.5, 3));                 // optional positional defaults to 0
  print(lineTotal(49.5, 3, 0.1));
  print(formatPrice(1499.5, decimals: 0));
  sendInvoice(amount: 1499.5, to: 'asha@example.com');   // any order
  // sendInvoice(to: 'x');                  // compile error: amount is required
}
```

## Prefer named parameters for booleans

`createUser('Asha', true, false)` is unreadable. `createUser('Asha', isAdmin: true, sendWelcome: false)` explains itself and cannot mix up the two flags.

**Quiz:** How do you make a named parameter mandatory in Dart?

- [x] Mark it with the required keyword
- [ ] Put it in square brackets
- [ ] Give it a default value
- [ ] Make it final

*Answer:* Mark it with the required keyword. Named parameters are optional unless marked required.
