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
// 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 dipanggilgreet(). - Anonymous function ditulis
function() { ... }(tanpa nama), wajib diakhiri titik koma karena ini adalah assignment ke variabel, dan dipanggil lewat variabel:$greet().
| Aspek | Named Function | Anonymous Function |
|---|---|---|
| Deklarasi | function greet($name) { ... } | $greet = function($name) { ... }; |
| Panggil | greet("Andi") — langsung pakai nama | $greet("Andi") — lewat variabel |
| Catatan | Nama dipakai langsung | Disimpan ke variabel dulu, wajib titik koma |
Anonymous Function
<?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.
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
$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
// 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 use | Nilai saat closure dibuat | Nilai saat closure dipanggil |
|---|---|---|
use ($var) | Disalin | Tetap nilai salinan lama |
use (&$var) | Menunjuk variabel asli | Ikut nilai terbaru |
use + By Reference untuk Counter
<?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
// 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
| Aspek | Anonymous | Arrow (fn) |
|---|---|---|
| Syntax | function($x) { return ...; } | fn($x) => ... |
| Menangkap variabel luar | Wajib use ($var) | Otomatis (by value) |
| Isi | Banyak statement bebas | Hanya satu expression |
| Mengubah variabel luar | Bisa dengan use (&$var) | Tidak bisa |
| Return | Wajib return eksplisit | Implisit (hasil expression) |
| Kapan cocok | Logika kompleks | Transformasi singkat |
<?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
?>
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
$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
$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
// ❌ 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
$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
$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
- Pakai arrow function (
fn) untuk transformasi singkat — lebih bersih dan otomatis menangkap variabel luar. - Pakai anonymous function untuk logika multi-statement atau saat perlu
use (&$var). - Closure +
useby reference adalah cara aman untuk membuat counter/akumulator stateful. - Callback + array functions (
array_map,array_filter,usort) menggantikan banyak foreach manual.
Exercise
- Buat anonymous function untuk filter array
- Gunakan arrow function untuk map array
- Jelaskan perbedaan anonymous function dan arrow function
- Buat closure dengan
useyang menghitung harga setelah diskon (diskon diambil dari variabel luar) - Gunakan
usortdengan closure untuk mengurutkan array mahasiswa berdasarkan umur - Buat counter menggunakan closure +
use (&$count), panggil 5 kali, lalu tampilkan hasilnya
Summary
| Poin | Penjelasan |
|---|---|
| Anonymous function | Function tanpa nama, disimpan ke variabel |
| Closure | Anonymous function yang menangkap variabel luar |
use ($var) | Mengimpor variabel luar (by value) |
use (&$var) | Mengimpor variabel luar (by reference) |
| Arrow function | fn($x) => expr — ringkas, satu expression |
| Auto-capture | Arrow function menangkap variabel luar otomatis |
| Callback | Closure sebagai argument: usort, array_map, array_filter |
| Titik koma | Wajib setelah } saat assignment ke variabel |
Klik tombol ini setelah menyelesaikan materi
Quiz Bab 6
Uji pemahamanmu tentang Function