Robuuste functies schrijven met stop() en warning()
Signaleer aangepaste condities vanuit uw eigen functies.
Robuuste functies schrijven met stop() en warning() is een gratis R Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject R Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus R Academy bevat in totaal 4 lessen.
Waarom invoervalidatie belangrijk is
Defensieve functies controleren hun invoer en mislukken duidelijk met informatieve fouten, in plaats van stilzwijgend verkeerde resultaten te produceren. Een functie die ongeldige invoer aan de grens opvangt, is veel eenvoudiger te debuggen dan een functie die onbruikbare gegevens door een pijplijn laat gaan.
# 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'))Informatieve foutmeldingen
Algemene fouten zoals stop('bad input') zijn frustrerend om te debuggen. Gebruik paste0() of sprintf() binnen stop() om de werkelijke waarde en het verwachte type in het bericht op te nemen. Dit bespaart tijd bij het traceren van fouten in pijplijnen.
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'))Lengte en bereik valideren
Veelvoorkomende validaties zijn: controleren of een vector niet leeg is (length(x) == 0), of een scalaire waarde binnen een bepaald bereik valt, of een gegevensframe de verwachte kolommen heeft. Elke controle moet een eigen, passende foutmelding hebben.
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'))warning() gebruiken voor niet-fatale problemen
Gebruik warning() wanneer de functie nog steeds een zinvol resultaat kan retourneren, maar de aanroeper moet weten dat er iets ongebruikelijks is gebeurd — bijvoorbeeld bij het converteren van een waarde, het invullen van een standaardwaarde of het detecteren van invoer op de grens.
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 in stop()
Standaard zet stop() Error in funcname(...): vóór het bericht. Geef call. = FALSE door om dit voorvoegsel te onderdrukken wanneer de aanroepende context duidelijk is of wanneer de functie bedoeld is als hulpfunctie voor gebruikers.
# 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'))Aangepaste voorwaardeklassen voor stop()
Maak met structure() een aangepaste foutklasse, zodat aanroepers alleen de fouten van jouw functie kunnen opvangen zonder alle fouten op te vangen. Dit is de professionele manier om fouten op pakketniveau te schrijven.
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'))Kolommen van gegevensframes controleren
Wanneer een functie een gegevensframe verwacht, valideer je voordat je de kolommen gebruikt of de vereiste kolommen bestaan. Gebruik %in% om kolomnamen te controleren en setdiff() om te melden welke kolommen ontbreken.
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() voor beknopte beweringen
stopifnot(condition1, condition2, ...) veroorzaakt een fout als een van de voorwaarden FALSE is. Het is een beknopte manier om voorwaarden vooraf boven aan een functie te controleren zonder afzonderlijke blokken met if (!...) stop(...) te schrijven.
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() met namen voor betere berichten
In R 4.0+ vervangen benoemde expressies in stopifnot() het automatisch gegenereerde bericht door jouw aangepaste beschrijving. Gebruik de tekst van de expressie als naam om informatieve foutmeldingen te produceren.
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'))Validatie en bedrijfslogica combineren
Een goed opgebouwde functie scheidt validatie van logica. Voer bovenaan de validatie uit en daarna de bewerking. Hierdoor is de functie eenvoudiger te lezen en worden fouten gedetecteerd voordat er berekeningen beginnen.
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 in hulpfuncties
Soms moet een hulpfunctie fouten intern afhandelen en een terugvalwaarde retourneren in plaats van ze door te geven. Plaats de kernlogica in tryCatch() en retourneer bij mislukking een afgesproken uitzonderingswaarde, zoals NA of NULL.
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')Snelle controle
Wat doet call. = FALSE wanneer je dit doorgeeft aan stop()?
Robuuste functies: belangrijkste punten
Belangrijkste punten voor het schrijven van robuuste functies:
- Valideer invoer bovenaan en laat de functie duidelijk mislukken met informatieve berichten van
stop() - Neem de werkelijke waarde op in foutmeldingen:
paste0('Expected numeric, got: ', class(x)) - Gebruik
warning()voor niet-fatale problemen waarbij de berekening kan doorgaan call. = FALSEonderdrukt het voorvoegsel van de aanroepende functie in foutmeldingen- Gebruik
stopifnot()voor beknopte beweringen en de benoemde vorm voor aangepaste berichten (R 4.0+) - Met aangepaste voorwaardeklassen kunnen aanroepers selectief opvangen
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'))Leer R met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 43
- Lessen
- 159
Veelgestelde vragen
Is de les “Robuuste functies schrijven met stop() en warning()” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad R Academy, waaronder “Robuuste functies schrijven met stop() en warning()”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus R Academy bevat in totaal 4 lessen.
Wat leer ik in “Robuuste functies schrijven met stop() en warning()”?
Signaleer aangepaste condities vanuit uw eigen functies. Je oefent met R Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met R Academy te beginnen?
Ervaring vooraf is niet nodig. R Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Robuuste functies schrijven met stop() en warning()”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over R Academy?
Ja. Elke les over R Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Fouten, waarschuwingen en berichten in R
- tryCatch() voor foutafhandeling
- withCallingHandlers() en restarts
- Robuuste functies schrijven met stop() en warning()