0Pricing
R Academy · Pelajaran

Menulis Fungsi Tangguh dengan stop() dan warning()

Kirim kondisi kustom dari dalam fungsi Anda sendiri.

Menulis Fungsi Tangguh dengan stop() dan warning() adalah pelajaran R Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar R Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus R Academy mencakup 4 pelajaran total.

Mengapa Validasi Masukan Penting

Fungsi defensif memeriksa masukannya dan gagal secara jelas dengan error yang informatif, bukan menghasilkan hasil yang salah secara diam-diam. Fungsi yang menangkap masukan buruk di batas awal jauh lebih mudah di-debug daripada fungsi yang meneruskan data tidak valid melalui alur pemrosesan.

# Without validation: wrong result, no error
bad_mean <- function(x) sum(x) / length(x)
bad_mean('hello')   # no error, just NA

# With validation: clear error
good_mean <- function(x) {
  if (!is.numeric(x)) stop('x must be numeric')
  sum(x) / length(x)
}
tryCatch(good_mean('hello'), error = function(e) cat(e$message, '\n'))

Pesan Error yang Informatif

Error umum seperti stop('bad input') sulit untuk di-debug. Gunakan paste0() atau sprintf() di dalam stop() untuk menyertakan nilai sebenarnya dan jenis yang diharapkan dalam pesan. Ini menghemat waktu saat menelusuri error dalam alur pemrosesan.

check_numeric <- function(x, arg_name = 'x') {
  if (!is.numeric(x)) {
    stop(sprintf(
      "'%s' must be numeric, but got class '%s'",
      arg_name, class(x)
    ))
  }
}
tryCatch(check_numeric('abc', 'score'),
  error = function(e) cat(e$message, '\n'))

Memvalidasi Panjang dan Rentang

Validasi umum meliputi pemeriksaan bahwa vektor tidak kosong (length(x) == 0), bahwa skalar berada dalam rentang tertentu, atau bahwa kerangka data memiliki kolom yang diharapkan. Setiap pemeriksaan sebaiknya memiliki pesan error khusus.

validate_prob <- function(p) {
  if (!is.numeric(p)) stop(paste0('p must be numeric, got: ', class(p)))
  if (length(p) != 1) stop(paste0('p must be length 1, got: ', length(p)))
  if (p < 0 || p > 1) stop(paste0('p must be in [0,1], got: ', p))
  p
}
cat(validate_prob(0.7), '\n')
tryCatch(validate_prob(1.5), error = function(e) cat(e$message, '\n'))

Menggunakan warning() untuk Masalah yang Tidak Fatal

Gunakan warning() saat fungsi masih dapat mengembalikan hasil yang masuk akal, tetapi pemanggil perlu mengetahui bahwa sesuatu yang tidak biasa terjadi — misalnya saat mengonversi nilai, mengisi nilai bawaan, atau mendeteksi masukan yang berada di ambang batas.

clamp <- function(x, lo, hi) {
  if (any(x < lo)) warning(paste0(sum(x < lo), ' value(s) below lo, clamped'))
  if (any(x > hi)) warning(paste0(sum(x > hi), ' value(s) above hi, clamped'))
  pmax(lo, pmin(hi, x))
}
result <- clamp(c(2, -5, 7, 100, 4), 0, 10)
cat('Result:', result, '\n')

call. = FALSE dalam stop()

Secara bawaan, stop() menambahkan Error in funcname(...): di awal pesan. Berikan call. = FALSE untuk menekan awalan ini saat konteks pemanggilan sudah jelas atau saat fungsi tersebut merupakan utilitas yang ditujukan bagi pengguna.

# With call. = TRUE (default): shows calling function
f1 <- function(x) stop('bad input')
tryCatch(f1(1), error = function(e) cat(conditionMessage(e), '\n'))

# With call. = FALSE: cleaner message
f2 <- function(x) stop('bad input', call. = FALSE)
tryCatch(f2(1), error = function(e) cat(conditionMessage(e), '\n'))

Kelas Kondisi Khusus untuk stop()

Buat kelas error khusus menggunakan structure() agar pemanggil dapat menangkap hanya error dari fungsi Anda tanpa menangkap semua error. Ini adalah cara profesional untuk menulis error tingkat paket.

value_error <- function(msg, call = sys.call(-1)) {
  structure(
    class = c('value_error', 'error', 'condition'),
    list(message = msg, call = call)
  )
}
check_positive <- function(x) {
  if (x <= 0) stop(value_error(paste0('Expected positive, got: ', x)))
  x
}
tryCatch(check_positive(-3),
  value_error = function(e) cat('ValueError:', e$message, '\n'),
  error        = function(e) cat('Other error:', e$message, '\n'))

Memeriksa Kolom Kerangka Data

Saat sebuah fungsi mengharapkan kerangka data, validasikan bahwa kolom yang diperlukan ada sebelum menggunakannya. Gunakan %in% untuk memeriksa nama kolom dan setdiff() untuk melaporkan kolom yang hilang.

require_cols <- function(df, cols) {
  missing <- setdiff(cols, names(df))
  if (length(missing) > 0) {
    stop(paste0('Missing columns: ', paste(missing, collapse = ', ')))
  }
  invisible(df)
}
df <- data.frame(x = 1:3, y = 4:6)
tryCatch(
  require_cols(df, c('x', 'z', 'w')),
  error = function(e) cat(e$message, '\n')
)

stopifnot() untuk Pernyataan Ringkas

stopifnot(condition1, condition2, ...) menghasilkan error jika salah satu kondisi bernilai FALSE. Ini adalah cara ringkas untuk menegaskan prasyarat di bagian awal fungsi tanpa menulis blok if (!...) stop(...) secara terpisah.

compute_area <- function(width, height) {
  stopifnot(
    is.numeric(width),
    is.numeric(height),
    width > 0,
    height > 0
  )
  width * height
}
cat(compute_area(5, 3), '\n')
tryCatch(compute_area(-1, 3), error = function(e) cat(e$message, '\n'))

stopifnot() Bernama untuk Pesan yang Lebih Baik

Dalam R 4.0+, ekspresi bernama di stopifnot() menggantikan pesan yang dibuat otomatis dengan deskripsi khusus Anda. Gunakan teks ekspresi sebagai nama untuk menghasilkan kegagalan yang informatif.

validate_age <- function(age) {
  stopifnot(
    'age must be numeric'    = is.numeric(age),
    'age must be positive'   = age > 0,
    'age must be under 150'  = age < 150
  )
  invisible(age)
}
tryCatch(validate_age(-5), error = function(e) cat(e$message, '\n'))
tryCatch(validate_age('x'), error = function(e) cat(e$message, '\n'))

Menggabungkan Validasi dan Logika Bisnis

Fungsi yang terstruktur dengan baik memisahkan validasi dari logika. Lakukan validasi di bagian awal, lalu jalankan operasi. Hal ini membuat fungsi lebih mudah dibaca dan memastikan error terdeteksi sebelum perhitungan dimulai.

discount_price <- function(price, pct) {
  if (!is.numeric(price) || price <= 0)
    stop(paste0('price must be positive numeric, got: ', price))
  if (!is.numeric(pct) || pct < 0 || pct > 100)
    stop(paste0('pct must be in [0,100], got: ', pct))
  if (pct > 50) warning('discount > 50% is unusual')
  price * (1 - pct / 100)
}
cat(discount_price(100, 20), '\n')
cat(suppressWarnings(discount_price(100, 60)), '\n')

tryCatch di Dalam Fungsi Utilitas

Terkadang fungsi utilitas sebaiknya menangani error secara internal dan mengembalikan nilai pengganti alih-alih meneruskannya. Bungkus logika inti dalam tryCatch() dan kembalikan penanda yang telah disepakati, seperti NA atau NULL, saat terjadi kegagalan.

safe_log <- function(x) {
  tryCatch({
    if (!is.numeric(x)) stop('not numeric')
    if (x <= 0) stop('must be positive')
    log(x)
  }, error = function(e) {
    warning(paste0('safe_log failed for x=', x, ': ', e$message))
    NA_real_
  })
}
results <- sapply(list(10, -1, 'a', 100), safe_log)
cat(results, '\n')

Pemeriksaan Singkat

Apa yang dilakukan call. = FALSE saat diberikan ke stop()?

Fungsi Tangguh: Inti Pembelajaran

Inti pembelajaran untuk menulis fungsi yang tangguh:

  • Validasikan masukan di bagian awal; gagal secara jelas dengan pesan stop() yang informatif
  • Sertakan nilai sebenarnya dalam pesan error: paste0('Expected numeric, got: ', class(x))
  • Gunakan warning() untuk masalah yang tidak fatal dan memungkinkan perhitungan berlanjut
  • call. = FALSE menekan awalan fungsi pemanggil dalam pesan error
  • stopifnot() untuk pernyataan ringkas; bentuk bernama untuk pesan khusus (R 4.0+)
  • Kelas kondisi khusus memungkinkan penangkapan selektif oleh pemanggil
robust_divide <- function(x, y) {
  stopifnot('x must be numeric' = is.numeric(x),
            'y must be numeric' = is.numeric(y))
  if (y == 0) stop('Division by zero', call. = FALSE)
  if (abs(y) < 1e-10) warning('y is very small; result may be inaccurate')
  x / y
}
cat(robust_divide(10, 2), '\n')
tryCatch(robust_divide(10, 0), error = function(e) cat(e$message, '\n'))

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Menulis Fungsi Tangguh dengan stop() dan warning()” gratis?

Ya — teks lengkap “Menulis Fungsi Tangguh dengan stop() dan warning()” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus R Academy, upgrade ke CoddyKit PRO. Kursus R Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Menulis Fungsi Tangguh dengan stop() dan warning()”?

Kirim kondisi kustom dari dalam fungsi Anda sendiri. Kamu berlatih R Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai R Academy?

Tidak diperlukan pengalaman sebelumnya. R Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “Menulis Fungsi Tangguh dengan stop() dan warning()” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran R Academy ini?

Ya. Setiap pelajaran R Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Error, Peringatan, dan Pesan dalam R
  2. tryCatch() untuk Pemulihan dari Error
  3. withCallingHandlers() dan Restart
  4. Menulis Fungsi Tangguh dengan stop() dan warning()
← Kembali ke R Academy