BAB 6: FUNCTION

6-4: Anonymous Function

Objectives

  • Membuat anonymous function (closure)
  • Menggunakan use untuk external variables
  • Arrow functions
  • Memahami perbedaan anonymous function dan arrow function
  • Menggunakan closure sebagai callback

Apa itu Anonymous Function?

Anonymous function adalah function tanpa nama. Daripada dideklarasikan dengan function nama(), function ini biasanya disimpan ke variabel atau langsung dikirim sebagai argument ke function lain.

php
<?php

// Function biasa: punya nama
function greet($name) {
    return "Halo, $name";
}

// Anonymous function: tidak punya nama
$greet = function($name) {
    return "Halo, $name";
};

echo greet("Andi") . "\n";       // Halo, Andi
echo $greet("Budi") . "\n";      // Halo, Budi

?>

Perhatikan perbedaannya:

  • Function biasa dideklarasikan dengan function greet() { ... } dan dipanggil greet().
  • Anonymous function ditulis function() { ... } (tanpa nama), wajib diakhiri titik koma karena ini adalah assignment ke variabel, dan dipanggil lewat variabel: $greet().
AspekNamed FunctionAnonymous Function
Deklarasifunction greet($name) { ... }$greet = function($name) { ... };
Panggilgreet("Andi") — langsung pakai nama$greet("Andi") — lewat variabel
CatatanNama dipakai langsungDisimpan ke variabel dulu, wajib titik koma

Anonymous Function

php
<?php

// Assign to variable
$greet = function($name) {
    echo "Hello, $name!\n";
};

$greet("Andi");  // Hello, Andi!
$greet("Budi");  // Hello, Budi!

// Sebagai parameter
$numbers = [3, 1, 4, 1, 5];
usort($numbers, function($a, $b) {
    return $a <=> $b;
});

print_r($numbers);
// Output: Array ( [0] => 1 [1] => 1 [2] => 3 [3] => 4 [4] => 5 )

?>

usort() adalah function bawaan PHP untuk mengurutkan array, dan ia menerima callback — function yang dipanggil PHP sendiri di dalam usort. Di sinilah anonymous function bersinar: kamu bisa mendefinisikan logika sorting di tempat, tanpa membuat function bernama khusus.

💡Tip

Skenario paling umum untuk anonymous function: callback. Function-function bawaan PHP seperti usort(), array_map(), array_filter(), dan array_reduce() menerima callback — dan anonymous function adalah cara paling praktis untuk memberikannya.

Closure dengan use

Closure adalah anonymous function yang "menangkap" variabel dari scope sekitarnya. Tanpa use, variabel luar tidak terlihat di dalam closure:

php
<?php

$multiplier = 2;

// ❌ Error/warning: $multiplier tidak terlihat
// $double = function($number) {
//     return $number * $multiplier;
// };

// ✅ use - access external variable
$double = function($number) use ($multiplier) {
    return $number * $multiplier;
};

echo $double(5);  // 10

?>

Kata kunci use "mengimpor" variabel dari luar ke dalam closure. Tanpa use, closure hanya melihat parameter dan variabel yang dibuat di dalamnya.

use By Value vs By Reference

php
<?php

// By value (default): menangkap SALINAN nilai saat itu
$base = 10;
$addToBase = function($num) use ($base) {
    return $base + $num;
};

echo $addToBase(5) . "\n";  // 15
$base = 20;
echo $addToBase(5) . "\n";  // 15 — masih pakai nilai lama (10)!

// By reference: menangkap LINK ke variabel asli
$base = 10;
$addToBaseRef = function($num) use (&$base) {
    return $base + $num;
};

echo $addToBaseRef(5) . "\n";  // 15
$base = 20;
echo $addToBaseRef(5) . "\n";  // 25 — ikut perubahan $base

?>
Mode useNilai saat closure dibuatNilai saat closure dipanggil
use ($var)DisalinTetap nilai salinan lama
use (&$var)Menunjuk variabel asliIkut nilai terbaru

use + By Reference untuk Counter

php
<?php

$count = 0;

$increment = function() use (&$count) {
    $count++;
    return $count;
};

echo $increment() . "\n";  // 1
echo $increment() . "\n";  // 2
echo $count . "\n";        // 2 — $count ikut berubah!

?>

Arrow Function (PHP 7.4+)

Arrow function adalah bentuk ringkas dari anonymous function — ditulis dengan fn dan =>:

php
<?php

// Traditional anonymous
$square = function($x) {
    return $x * $x;
};

// Arrow function (lebih concise)
$square = fn($x) => $x * $x;

echo $square(5);  // 25

// Multiple parameters
$sum = fn($a, $b) => $a + $b;

echo $sum(3, 4) . "\n";  // 7

// Arrow functions otomatis use external variables
$base = 10;
$add = fn($x) => $base + $x;
echo $add(5);  // 15

?>

Perhatikan perbedaan penting: arrow function otomatis menangkap variabel dari scope luar — tidak perlu menulis use (...).

Anonymous vs Arrow Function

AspekAnonymousArrow (fn)
Syntaxfunction($x) { return ...; }fn($x) => ...
Menangkap variabel luarWajib use ($var)Otomatis (by value)
IsiBanyak statement bebasHanya satu expression
Mengubah variabel luarBisa dengan use (&$var)Tidak bisa
ReturnWajib return eksplisitImplisit (hasil expression)
Kapan cocokLogika kompleksTransformasi singkat
php
<?php

// Arrow function = satu expression saja
$discount = fn($price, $percent) => $price - ($price * $percent / 100);

echo $discount(100000, 10) . "\n";  // 90000

// Jika butuh banyak statement, gunakan anonymous function
$process = function($price) {
    $taxed = $price * 1.11;
    $rounded = round($taxed);
    return "Harga final: Rp " . number_format($rounded);
};

echo $process(100000) . "\n";
// Output: Harga final: Rp 111.000

?>
⚠️Perhatian

Arrow function tidak bisa berisi lebih dari satu expression, dan tidak bisa mengubah variabel luar (karena selalu menangkap by value). Jika kamu butuh logika bertingkat atau ingin memodifikasi variabel luar, gunakan anonymous function biasa.

Callback dengan array_map dan array_filter

Ini penggunaan closure paling umum di dunia nyata:

php
<?php

$prices = [10000, 25000, 50000, 150000];

// array_map: transformasi setiap elemen
$formatted = array_map(
    fn($price) => "Rp " . number_format($price),
    $prices
);

print_r($formatted);
/*
Output:
Array
(
    [0] => Rp 10.000
    [1] => Rp 25.000
    [2] => Rp 50.000
    [3] => Rp 150.000
)
*/

// array_filter: menyaring elemen
$cheap = array_filter($prices, fn($price) => $price < 50000);

print_r($cheap);
// Output: Array ( [0] => 10000 [1] => 25000 )

// Kombinasi dengan use: filter berdasarkan batas dinamis
$limit = 30000;
$affordable = array_filter(
    $prices,
    fn($price) => $price <= $limit   // otomatis menangkap $limit
);

print_r($affordable);
// Output: Array ( [0] => 10000 [1] => 25000 )

?>

Sorting dengan Closure

php
<?php

$students = [
    ["name" => "Andi", "score" => 85],
    ["name" => "Budi", "score" => 92],
    ["name" => "Citra", "score" => 78]
];

// Urutkan berdasarkan nilai (descending)
usort($students, function($a, $b) {
    return $b["score"] <=> $a["score"];
});

foreach ($students as $student) {
    echo $student["name"] . ": " . $student["score"] . "\n";
}

/*
Output:
Budi: 92
Andi: 85
Citra: 78
*/

?>

Operator <=> (spaceship) mengembalikan -1, 0, atau 1 — persis yang dibutuhkan function perbandingan untuk sorting.

Common Mistakes

Lupa Titik Koma Setelah Assignment

php
<?php

// ❌ Salah: lupa titik koma setelah }
// $greet = function($name) {
//     return "Halo, $name";
// }   // Parse error

// ✅ Benar: titik koma wajib karena ini assignment
$greet = function($name) {
    return "Halo, $name";
};

echo $greet("Andi") . "\n";  // Halo, Andi

?>

Lupa use untuk Variabel Luar

php
<?php

$tax = 0.11;

// ❌ $tax tidak terlihat di dalam closure
// $withTax = function($price) {
//     return $price * (1 + $tax);  // Undefined variable
// };

// ✅ Pakai use
$withTax = function($price) use ($tax) {
    return $price * (1 + $tax);
};

echo $withTax(100000) . "\n";  // 111000

?>

Arrow Function Mencoba Mengubah Variabel Luar

php
<?php

$total = 0;
$prices = [10000, 20000, 30000];

// ❌ Tidak bisa: arrow function menangkap by value
// $addAll = fn($price) => $total += $price;  // Tidak mengubah $total asli

// ✅ Gunakan anonymous + use by reference
$addAll = function($price) use (&$total) {
    $total += $price;
};

array_map($addAll, $prices);
echo "Total: $total\n";  // Total: 60000

?>

Pro Tips

  1. Pakai arrow function (fn) untuk transformasi singkat — lebih bersih dan otomatis menangkap variabel luar.
  2. Pakai anonymous function untuk logika multi-statement atau saat perlu use (&$var).
  3. Closure + use by reference adalah cara aman untuk membuat counter/akumulator stateful.
  4. Callback + array functions (array_map, array_filter, usort) menggantikan banyak foreach manual.

Exercise

  1. Buat anonymous function untuk filter array
  2. Gunakan arrow function untuk map array
  3. Jelaskan perbedaan anonymous function dan arrow function
  4. Buat closure dengan use yang menghitung harga setelah diskon (diskon diambil dari variabel luar)
  5. Gunakan usort dengan closure untuk mengurutkan array mahasiswa berdasarkan umur
  6. Buat counter menggunakan closure + use (&$count), panggil 5 kali, lalu tampilkan hasilnya

Summary

PoinPenjelasan
Anonymous functionFunction tanpa nama, disimpan ke variabel
ClosureAnonymous function yang menangkap variabel luar
use ($var)Mengimpor variabel luar (by value)
use (&$var)Mengimpor variabel luar (by reference)
Arrow functionfn($x) => expr — ringkas, satu expression
Auto-captureArrow function menangkap variabel luar otomatis
CallbackClosure sebagai argument: usort, array_map, array_filter
Titik komaWajib setelah } saat assignment ke variabel

Klik tombol ini setelah menyelesaikan materi

📝

Quiz Bab 6

Uji pemahamanmu tentang Function