# Functions, Named Arguments and Closures — PHP

Source: https://www.skillbyai.com/en/php/c-functions

> Write typed functions with defaults, named arguments, variadics and closures.

## Reusable behaviour

Functions take typed parameters and declare a return type: `function total(array $items, float $discount = 0.0): float`. **Named arguments** (PHP 8.0) let callers pass arguments by name in any order and skip optional ones: `total(items: $cart, discount: 0.1)`, which makes calls with many options readable. **Variadics** (`int ...$numbers`) accept any number of arguments, and the spread operator (`...$array`) unpacks arrays into arguments. The **nullsafe operator** `?->` short-circuits method chains when a value is null. **Anonymous functions (closures)** capture outer variables explicitly with `use ($rate)`, by value unless written `use (&$total)`. **Arrow functions** (`fn ($x) => $x * $rate`) capture outer variables automatically by value and contain a single expression, perfect for `array_map` and `array_filter`. **First-class callable syntax** (PHP 8.1), `strlen(...)` or `$this->format(...)`, creates a closure from any callable. Return type **`never`** marks functions that always throw or exit, and **`void`** functions return nothing.

## Modern function features

Named arguments, variadics, closures and arrow functions.

```php
<?php
declare(strict_types=1);

function formatPrice(float $amount, string $currency = 'INR', int $decimals = 2): string
{
    return number_format($amount, $decimals) . ' ' . $currency;
}

echo formatPrice(1499.5, decimals: 0), PHP_EOL;     // named argument skips $currency

function sum(int ...$numbers): int
{
    return array_sum($numbers);
}
echo sum(...[10, 20, 30]), PHP_EOL;                  // spread an array into arguments

$rate = 0.18;
$withTax = array_map(fn (float $p): float => round($p * (1 + $rate), 2), [100.0, 250.0]);

$total = 0;
$add = function (int $n) use (&$total): void { $total += $n; };
$add(5);
$add(7);                                             // $total is now 12

$lengths = array_map(strlen(...), ['pen', 'notebook']);   // first-class callable

$city = $user?->getAddress()?->city ?? 'unknown';    // nullsafe chain
```

## Labelled switches on a control panel

Positional arguments are a row of unlabelled switches: you must remember which one is which. Named arguments put a label on each switch, so `discount: 0.1` is obvious to every reader.

**Quiz:** How does an arrow function access a variable from the surrounding scope?

- [ ] It cannot
- [x] It captures it automatically by value
- [ ] Only with use (&$var)
- [ ] Only through global

*Answer:* It captures it automatically by value. Arrow functions capture outer variables by value automatically; closures need an explicit use clause.
