Error Rust E0057: this function takes N arguments but M were supplied (closure)
E0057 artinya kamu memanggil sebuah closure (fungsi anonim) dengan jumlah argumen yang salah: terlalu sedikit atau terlalu banyak. Ini versi closure dari E0061, dan pesannya hampir sama persis. Perbaikannya biasanya cepat: lihat |...| milik closure itu, lalu berikan satu nilai untuk setiap parameter. Halaman ini juga membahas dua kerabat dekatnya yang akan kamu temui saat memakai iterator, E0593 dan E0631, karena keduanya berasal dari kekeliruan yang sama. Untuk error lain di seri ini, lihat Penjelasan error compiler Rust.
Pesan error-nya
Section titled “Pesan error-nya”error[E0057]: this function takes 2 arguments but 1 argument was supplied --> src/main.rs:3:17 |3 | let total = add(1); // ❌ add butuh dua angka | ^^^--- argument #2 of type `i32` is missing |note: closure defined here --> src/main.rs:2:15 |2 | let add = |a: i32, b: i32| a + b; | ^^^^^^^^^^^^^^^^help: provide the argument |3 | let total = add(1, /* i32 */); // ❌ add butuh dua angka | +++++++++++Compiler bilang closure ini butuh 2 argumen tapi hanya diberi 1, argumen ke-2 bertipe i32 belum ada, dan ia menunjukkan di mana closure itu didefinisikan.
Ini program yang menghasilkan error tersebut:
fn main() { let add = |a: i32, b: i32| a + b; let total = add(1); // ❌ add butuh dua angka println!("{total}");}Argumen yang terlalu banyak memberi kode yang sama, dengan label “unexpected argument” (argumen tak terduga) dan bantuan “remove the extra argument” (hapus argumen yang berlebih):
error[E0057]: this function takes 1 argument but 2 arguments were supplied --> src/main.rs:3:5 |3 | greet("Ferris", "Corro"); | ^^^^^ ------- unexpected argument #2 of type `&'static str` |note: closure defined hereApa artinya
Section titled “Apa artinya”Baca pesannya seperti pesan untuk fungsi biasa: baris pertama menghitung (closure-nya menerima 2, kamu memberi 1), label di bawah pemanggilanmu menyebut argumen mana yang kurang atau berlebih, dan help: menunjukkan tempatnya. /* i32 */ hanyalah komentar penanda yang memberitahu tipenya. Isi dengan nilai sungguhan.
E0057 atau E0061? Baris pertamanya sama. Yang membedakan adalah note:-nya:
closure defined here: kamu memanggil closure. Itu E0057.callable defined here: kamu memanggilfgenerik dengan bound sepertiF: Fn(i32). Ini juga E0057.function defined here:fnbiasa, method, atau function pointer (let f: fn(i32, i32) -> i32 = add;). Itu E0061.
Apa pun kasusnya, perbaikannya sama: samakan pemanggilan dengan daftar parameternya.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Daftar parameter closure sama tetapnya dengan daftar parameter fungsi. |a: i32, b: i32| menerima tepat dua i32, setiap kali. Tidak ada argumen default dan tidak ada “boleh kasih lebih sedikit kalau mau”. Bahkan kalau kamu tidak menulis tipenya, rustc menyimpulkannya dari isi closure dan pemakaian pertamanya, dan sejak itu tipenya terkunci.
Di balik layar, closure mengimplementasikan salah satu trait Fn dengan daftar tipe argumen yang tetap, seperti Fn(i32, i32) -> i32. Compiler memeriksa setiap pemanggilan terhadap daftar itu, jadi pemanggilan dengan jumlah argumen yang salah tidak akan pernah sampai ke program yang berjalan. Cara kerja closure dan parameternya dibahas di Closure dan Trait closure.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Samakan pemanggilan dengan parameter closure
Section titled “Perbaikan 1: Samakan pemanggilan dengan parameter closure”Pilih ini hampir setiap saat. Lompat ke lokasi note:, hitung parameter di antara tanda pipa |...|, dan berikan satu nilai untuk masing-masing. Kalau nilaimu lebih banyak daripada parameternya, panggil closure itu lebih dari sekali:
fn main() { let add = |a: i32, b: i32| a + b; let greet = |name: &str| println!("Halo, {name}!");
let total = add(1, 2); println!("{total}");
greet("Ferris"); greet("Corro"); // satu pemanggilan per nama}Output:
3Halo, Ferris!Halo, Corro!Kalau closure-nya memang seharusnya menerima jumlah nilai yang berbeda, ubah closure-nya saja. Itu juga tidak masalah, asalkan setiap pemanggilan sesuai dengannya.
Perbaikan 2: Tuple: satu tuple adalah satu argumen
Section titled “Perbaikan 2: Tuple: satu tuple adalah satu argumen”Pilih ini kalau ada tuple yang terlibat. |(name, score)| dan |name, score| kelihatan mirip, tapi keduanya closure yang berbeda. Yang pertama menerima satu argumen, yaitu sebuah tuple, lalu membongkarnya. Yang kedua menerima dua argumen.
Memanggil closure tuple dengan dua nilai memberi E0057, dan rustc menyarankan untuk menambahkan tanda kurung:
error[E0057]: function takes 1 argument but 2 arguments were supplied --> src/main.rs:3:5 |3 | show("Ferris", 90); | ^^^^ |note: closure parameter defined herehelp: wrap these arguments in parentheses to construct a tuple |3 | show(("Ferris", 90)); | + +Kesalahan sebaliknya sering sekali terjadi dengan iterator. zip, enumerate, dan iterasi atas map memberi closure-mu satu tuple per item. Menulis .map(|name, score| ...) memberi kode yang berbeda, E0593:
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments --> src/main.rs:7:10 |7 | .map(|name, score| format!("{name}: {score}")) | ^^^ ------------- takes 2 distinct arguments | | | expected closure that takes a single 2-tuple as argument |help: change the closure to accept a tuple instead of individual arguments |7 - .map(|name, score| format!("{name}: {score}"))7 + .map(|(name, score)| format!("{name}: {score}"))Compiler bilang closure itu seharusnya menerima satu tuple berisi 2 elemen, tapi kamu menulis 2 argumen terpisah. Keduanya punya perbaikan yang sama: taruh tanda kurung di tempat tuple-nya berada.
fn main() { let names = vec!["Ferris", "Corro"]; let scores = vec![90, 75];
// zip memberi satu tuple (name, score) per item: bongkar di daftar parameter let lines: Vec<String> = names .iter() .zip(scores.iter()) .map(|(name, score)| format!("{name}: {score}")) .collect(); println!("{:?}", lines);
// closure yang menerima tuple dipanggil dengan satu tuple let show = |(name, score): (&str, i32)| println!("{name} mendapat nilai {score}"); show(("Ferris", 90));}Output:
["Ferris: 90", "Corro: 75"]Ferris mendapat nilai 90Hal yang sama berlaku untuk .enumerate().map(|(i, item)| ...) dan map.iter().for_each(|(key, value)| ...). Lihat Iterator dan Tuple.
Perbaikan 3: Sesuaikan dengan closure pembungkus
Section titled “Perbaikan 3: Sesuaikan dengan closure pembungkus”Pilih ini kalau kamu memberikan sebuah fungsi atau closure ke fungsi lain (sebuah “higher-order function”) dan jumlah parameternya tidak cocok. Di sini apply menginginkan sesuatu yang menerima satu i32, tapi add menerima dua. Hasilnya E0593 lagi:
error[E0593]: function is expected to take 1 argument, but it takes 2 arguments --> src/main.rs:10:26 | 5 | fn add(a: i32, b: i32) -> i32 { | ----------------------------- takes 2 arguments...10 | println!("{}", apply(add, 5)); | ----- ^^^ expected function that takes 1 argument | | | required by a bound introduced by this callCompiler bilang apply mengharapkan fungsi yang menerima 1 argumen, tapi add menerima 2. Jangan ubah add. Bungkus dengan closure kecil yang bentuknya sesuai harapan apply, dan isi sendiri nilai yang kurang:
fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 { f(x)}
fn add(a: i32, b: i32) -> i32 { a + b}
fn main() { let bonus = 10; // menerima 1 argumen, memanggil add dengan 2 println!("{}", apply(|x| add(x, bonus), 5));
// menerima 1 tuple, memanggil add dengan kedua bagiannya let pairs = vec![(1, 2), (3, 4)]; let sums: Vec<i32> = pairs.into_iter().map(|(a, b)| add(a, b)).collect(); println!("{:?}", sums);}Output:
15[3, 7]Closure pembungkus itu meminjam bonus dari kode di sekitarnya, dan itulah keahlian closure. Memberikan fungsi lewat namanya (apply(double, 5)) hanya berhasil kalau parameternya sudah cocok. Lihat Trait closure.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Di dalam fungsi generik. fn call_twice<F: Fn(i32)>(f: F) yang memanggil f(2, 3) memberi E0057 dengan note: callable defined here, menunjuk ke Fn(i32). Bound itulah daftar parameternya. Perbaikan: panggil f(2), atau ubah bound-nya menjadi Fn(i32, i32) kalau kamu memang butuh dua nilai (maka closure dari setiap pemanggil harus menerima dua).
Closure dalam Box. let f: Box<dyn Fn(i32, i32) -> i32> = Box::new(|a, b| a + b); lalu f(1) memberi E0057 dengan note: implementation defined here. Perbaikan: berikan kedua nilai, f(1, 2).
Mengurutkan. v.sort_by(|a| a.cmp(a)) memberi E0593, “closure is expected to take 2 arguments, but it takes 1 argument”. sort_by membandingkan dua item sekaligus. Perbaikan: v.sort_by(|a, b| a.cmp(b)). Lihat Mengurutkan dan mencari.
Jumlahnya benar, tipenya salah. nums.iter().map(|x: i32| x * 2) memberi E0631, “type mismatch in closure arguments” (tipe argumen closure tidak cocok), karena .iter() memberikan &i32. Bantuan dari rustc menyarankan |x: &i32|. Perbaikan paling sederhana: hapus anotasinya, |x| x * 2.
Membongkar sesuatu yang bukan tuple. v.iter().map(|(a, b)| a + b) pada Vec<i32> biasa memberi E0308, “expected integer, found (_, _)”. Perbaikan: pakai |(a, b)| hanya kalau item-nya memang berpasangan.
Error terkait
Section titled “Error terkait”- E0061: wrong number of arguments: pesan yang sama untuk fungsi biasa, method, dan function pointer.
- E0308: mismatched types: jumlahnya benar, tapi sebuah argumen (atau pola tuple) bertipe salah.
- E0373: closure may outlive the current function: error closure lain yang umum, tentang variabel yang ditangkap di thread dan closure yang dikembalikan.
- E0599: no method found: bisa muncul bersama E0631, karena closure dengan signature yang salah merusak sisa rangkaian iterator.
- E0593: closure takes 2 distinct arguments: closure atau fungsi diberikan dengan jumlah parameter yang salah.
- E0631: type mismatch in closure arguments: jumlah parameternya benar, tapi tipenya salah.
- Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. let double = |x: i32| x * 2; dipanggil sebagai double(2, 3). Apa yang dilaporkan rustc?
2. names.iter().zip(ages.iter()).map(|n, a| ...) tidak bisa dikompilasi. Apa perbaikannya?
3. E0057 dan E0061 sama-sama bilang this function takes 2 arguments but 1 argument was supplied. Bagaimana kamu tahu yang kamu panggil adalah closure?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0057 — Rust error codes index (bahasa Inggris): penjelasan resmi error ini.
- Closures — The Rust Book (bahasa Inggris): sintaks closure, inferensi tipe untuk parameter, dan trait
Fn. - Closures — Rust by Example (bahasa Inggris): contoh singkat yang bisa dijalankan tentang closure, termasuk memberikannya ke fungsi.
std::ops::Fn— dokumentasi standard library (bahasa Inggris): bagaimana boundFn(i32) -> i32menggambarkan parameter sebuah closure.- E0593 — Rust error codes index (bahasa Inggris): penjelasan resmi error closure yang diberikan dengan jumlah parameter yang salah.