# Functions

Course: [Dart](https://www.devtutorials.ai/learn/dart) · Section: Control Flow
Source: https://www.devtutorials.ai/learn/dart/control-flow/functions

> How to write and call functions, return values, positional, optional and named parameters, arrow and anonymous functions, closures, recursion and scope.

## What Is a Function?

**Function** = a named block of code that does one job. You can run it again and again by its name.

For example:

- `greet()` prints a welcome message
- `addGst(price)` works out a price with tax
- `isPass(marks)` answers `true` or `false`

You have already used functions: `main()` and `print()`.

**Simple lesson:** a function is a named piece of work you can reuse.

### A Real-World Example

Think of a pressure cooker.

- You put in **rice and water** (the inputs).
- It does the **same job** every time: cook.
- It gives back **cooked rice** (the output).
- You do not need to know what happens inside. You just use it.

A function is that machine: inputs go in, it does its job, and an answer comes out.

Every **Run** box on this page runs on the course's Dart runner in your browser.

Some boxes fail on purpose, to show a real error.

## What You Will Learn

In this lesson, you will learn:

1. How to define and call a function, and get a value back with `return`.
2. Positional, optional and named parameters, and default values.
3. Anonymous functions and arrow functions.
4. Higher-order functions, callbacks and closures.
5. Recursion and scope.

## Function Fundamentals

### Why Functions Are Used

- **Reuse:** write the code once, call it many times.
- **Fewer mistakes:** fix a bug in one place, and every call is fixed.
- **Easy to read:** `printReportCard()` says what it does.
- **Small pieces:** a big program becomes many small, simple functions.

### Defining a Function

```text
returnType functionName(parameters) {
  // body
}
```

- **Return type** = the type of value it gives back. `void` = nothing.
- **Function name** = lowerCamelCase, usually a verb: `printHeader`, `addMarks`.
- **Parameters** = the inputs, inside `( )`.
- **Body** = the code, inside `{ }`.

### Calling a Function

**Call** = run a function by writing its name and `( )`.

```dart runnable title="Define once, call many times"
void printLine() {
  print('------------------------');
}

void main() {
  printLine();
  print('GREEN VALLEY SCHOOL');
  printLine();
  print('Report Card 2026');
  printLine();
}
```

`printLine` was written once, and called three times.

**Simple lesson:** define a function once, then call it by name whenever you need it.

## Return Values

### return

**`return`** = send a value back to the caller, and stop the function.

**Return value** = the value a function gives back.

**Parameter** = the name in the function's definition, like `a`.

**Argument** = the actual value you pass in a call, like `78`.

### Returning Different Types

```dart runnable title="Functions that answer questions"
bool isPass(int marks) {
  return marks >= 35;
}

String grade(int marks) {
  if (marks >= 90) return 'A';
  if (marks >= 75) return 'B';
  return 'C';
}

void main() {
  print(isPass(42));
  print(isPass(20));
  print(grade(81));
}
```

`return` ends the function straight away. Code after it in that path does not run.

### void Functions

**`void`** = the function gives nothing back. It just does something, like printing.

```dart runnable title="A void function does a job"
void welcome(String name) {
  print('Welcome to Green Valley, $name!');
}

void main() {
  welcome('Kavya');
  welcome('Imran');
}
```

**Simple lesson:** `return` hands a value back, and `void` means the function only does a job.

## Function Parameters

### Required Positional Parameters

**Positional parameter** = an input matched by its **position** in the call.

- The first argument goes to the first parameter, and so on.
- All of them must be given, in the right order.

```dart runnable title="Order matters"
void showMarks(String name, int marks) {
  print('$name scored $marks.');
}

void main() {
  showMarks('Asha', 88);
  showMarks('Ravi', 74);
}
```

### Optional Positional Parameters

**Optional positional parameter** = an input in `[ ]` that the caller may leave out.

```dart runnable title="An optional section"
void showClass(String name, [String? section]) {
  print('$name, section: ${section ?? 'not given'}');
}

void main() {
  showClass('Asha', '8B');
  showClass('Ravi');
}
```

- Optional parameters go **last**, inside `[ ]`.
- If one is left out, it is `null`, so its type needs `?` (see **Null Safety**).

### Named Parameters

**Named parameter** = an input in `{ }` that the caller passes **by name**.

- In the call, write `name: value`.
- The order does not matter.
- Named parameters are optional, unless marked **`required`**.

```dart runnable title="Named parameters"
void addStudent({required String name, required int rollNumber, String? house}) {
  print('$rollNumber: $name, house: ${house ?? 'none'}');
}

void main() {
  addStudent(name: 'Meena', rollNumber: 12, house: 'Tagore');
  addStudent(rollNumber: 13, name: 'Kiran');
}
```

Named parameters make calls easy to read. `addStudent(name: 'Meena', rollNumber: 12)` explains itself.

### Default Values

**Default value** = the value a parameter uses when the caller leaves it out.

```dart runnable title="Default values"
void orderLunch(String item, {int quantity = 1, bool extraSpicy = false}) {
  print('$quantity x $item, extra spicy: $extraSpicy');
}

void main() {
  orderLunch('Samosa');
  orderLunch('Dosa', quantity: 2);
  orderLunch('Pav Bhaji', extraSpicy: true, quantity: 3);
}
```

**Simple lesson:** positional inputs go by order, named inputs go by name, and defaults fill the gaps.

## Anonymous Functions

**Anonymous function** = a function with **no name**. Also called a **function expression**.

```text
(parameters) {
  // body
}
```

You can store it in a variable, or pass it straight to another function.

```dart runnable title="A function without a name"
void main() {
  var shout = (String text) {
    return text.toUpperCase() + '!';
  };
  print(shout('jai hind'));

  var marks = [78, 92, 65];
  marks.forEach((m) {
    print('Mark: $m');
  });
}
```

**Simple lesson:** an anonymous function is a function you use right where you write it.

## Arrow Functions

**Arrow syntax (`=>`)** = a short way to write a function whose body is **one expression**.

`=> expr` means `{ return expr; }`.

```dart runnable title="Arrow functions"
int square(int n) => n * n;
bool isEven(int n) => n % 2 == 0;
String greet(String name) => 'Hello, $name!';

void main() {
  print(square(9));
  print(isEven(14));
  print(greet('Zoya'));

  var twice = (int n) => n * 2;
  print(twice(21));
}
```

**Single-expression function** = a function that only works out one value. Arrows are made for them.

- Use `=>` for **one** expression.
- Use `{ }` when you need several statements.

Dart's own code style uses `=>` for every function whose body is just one `return`.

You will see it everywhere in Flutter code, so it is worth getting used to now.

**Simple lesson:** `=> value` is short for `{ return value; }`.

## Higher-Order Functions

**Higher-order function** = a function that takes another function as an input, or gives one back.

### Functions as Values

In Dart, a function is a value, like a number. You can store it in a variable.

### Functions as Parameters and Callbacks

**Callback** = a function you pass to another function, so it can call it later.

```dart runnable title="Passing a function as an input"
int addGrace(int m) => m + 5;
int doubleIt(int m) => m * 2;

void changeAll(List<int> marks, int Function(int) rule) {
  for (var m in marks) {
    print(rule(m));
  }
}

void main() {
  var marks = [30, 50];
  changeAll(marks, addGrace);
  changeAll(marks, doubleIt);
  changeAll(marks, (m) => m - 1);
}
```

- **`int Function(int)`** = the type "a function that takes an `int` and gives an `int`".
- `changeAll` does not know the rule. The caller decides it.
- You will use this a lot in **Working with Iterables**, with `map` and `where`.

**Simple lesson:** a higher-order function takes a function as an input, so the caller can choose the behaviour.

## Closures

**Closure** = a function that **remembers** the variables around it, even after that code has finished.

**Lexical scope** = a function can use the variables of the place where it was **written**.

```dart runnable title="A counter that remembers"
Function makeTokenCounter() {
  var token = 0;
  return () {
    token++;
    return 'Token $token';
  };
}

void main() {
  var nextToken = makeTokenCounter();
  print(nextToken());
  print(nextToken());
  print(nextToken());
}
```

- `makeTokenCounter` finished long ago.
- But the returned function still remembers `token`, and keeps counting.

**Simple lesson:** a closure carries its own variables with it, like a backpack.

## Recursion

**Recursive function** = a function that **calls itself**.

Every recursive function needs two parts:

- **Base case** = when to stop. No more calls.
- **Recursive case** = call itself with a **smaller** problem.

### Factorial Example

**Factorial** = `5! = 5 × 4 × 3 × 2 × 1 = 120`.

Notice: `5! = 5 × 4!`, and `4! = 4 × 3!`, and so on, until `1! = 1`.

```dart runnable title="Factorial with recursion"
int factorial(int n) {
  if (n <= 1) {
    return 1;
  }
  return n * factorial(n - 1);
}

void main() {
  print(factorial(5));
  print(factorial(3));
}
```

- **Base case:** `n <= 1` returns `1`.
- **Recursive case:** `n * factorial(n - 1)`. Each call has a smaller `n`.

Without a base case, the function calls itself forever, and the program crashes with a **Stack Overflow**.

**Simple lesson:** recursion solves a problem by solving a smaller copy of it, until it reaches a base case.

## Function Scope

**Scope** = the part of the code where a variable can be used.

- **Local variable** = made inside a function. It exists only inside it.
- **Global variable** = made outside every function, at the top level. Every function can use it.

### Scope Rules

- Code **inside** a block can see variables from **outside** it.
- Code **outside** a block **cannot** see variables made inside it.
- A local variable disappears when its function ends.

```dart runnable title="Global and local variables"
var school = 'Green Valley';

void showTotal() {
  var total = 92 + 88;
  print('$school: total $total');
}

void main() {
  showTotal();
  print('School: $school');
}
```

`total` lives only inside `showTotal`. Try to use it outside:

```dart runnable expect-error title="A local variable cannot be seen outside"
void showTotal() {
  var total = 92 + 88;
}

void main() {
  print(total);
}
```

Dart says: `Undefined name 'total'.`

**Easy way to remember**

- **Parameters** = what goes **in**. **`return`** = what comes **out**.
- **`=>`** = a one-line function.
- **Local** variables stay **inside** their function.
- **Prefer local** variables. Global ones can be changed from anywhere, which causes bugs.

**Simple lesson:** a variable lives inside the `{ }` where it was made, and inner code can see outward.

## TL;DR

1. **Function** = a named, reusable block. Call it with `name()`.
   - **`return`** gives a value back. **`void`** gives nothing.
2. **Parameters:**
   - **Positional** = by order. **Optional `[ ]`** = may be left out.
   - **Named `{ }`** = by name, optional unless `required`. **Defaults** fill gaps.
3. **Anonymous function** = no name. **Arrow `=>`** = one-expression body.
4. **Higher-order function** = takes or returns a function. **Callback** = a function passed in.
   - **Closure** = a function that remembers its surrounding variables.
5. **Recursion** = a function calls itself, with a base case to stop.
   - **Scope** = local inside a function, global at the top level.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Forgetting `return` | The last value is returned | Write `return value;` | The function gives back `null`, or an error. |
| Using a `void` result | `void` functions give a value | They give nothing | `This expression has a type of 'void'`. |
| Arguments in the wrong order | Dart matches by name | Positional arguments go by order | The wrong values in the wrong places. |
| Leaving out a `required` named argument | All named ones are optional | `required` ones must be given | `Required named parameter must be provided`. |
| No base case | Recursion stops by itself | Every recursion needs a base case | Stack Overflow. |
| Using a local variable outside | Variables are visible everywhere | Locals live inside their function | `Undefined name`. |
| `=>` with several statements | Arrows can hold a block | `=>` takes one expression | A syntax error. |

## Check Yourself

## Exercises

## What to Remember

- A function is a named, reusable block. `return` gives a value back, and `void` gives nothing.
- Positional inputs go by order, `[ ]` makes them optional, and `{ }` makes them named.
- `=>` is a one-expression function, and an anonymous function has no name.
- Functions can be passed to other functions, and closures remember their variables.
- Recursion needs a base case. A local variable lives only inside its function.

Next: **Lists**. You will learn to store many values in one variable, in order.
