מאמתים ופונקציות עזר
חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 5 מתוך 57.
הבנאי בודק טיפוסים; מאמת בודק ערכים. לפי המוסכמה, validate_money() מקבלת אובייקט, קוראת ל־stop() עם הודעה ברורה עבור כל כלל שהוא מפר, ומחזירה את האובייקט כשהכול תקין. call. = FALSE מונע מהקריאה לפונקציה להופיע בהודעה:
new_money <- function(amount = double(), currency = character()) {
stopifnot(is.double(amount), is.character(currency))
structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
if (nchar(x$currency) != 3) stop("currency must have 3 letters", call. = FALSE)
x
}
m <- validate_money(new_money(-5, "EUR"))פלט:
Error: amount must not be negative
Execution haltedהפונקציית עזר היא הפונקציה שקוד אחר קורא לה. היא נקראת על שם המחלקה, ממירה את הקלט שלה לטיפוסים המתאימים, ממלאת ערכי ברירת מחדל ומעבירה את התוצאה דרך הבנאי והמאמת:
new_money <- function(amount = double(), currency = character()) {
stopifnot(is.double(amount), is.character(currency))
structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
x
}
money <- function(amount, currency = "EUR") {
validate_money(new_money(as.double(amount), toupper(currency)))
}
m <- money("12", "usd")
cat(m$amount, m$currency)פלט:
12 USDקוד שקורא קלט מהמשתמש תופס את השגיאות של המאמת באמצעות tryCatch() ומציג את conditionMessage(e), הטקסט שמועבר אל stop():
validate_age <- function(x) {
if (x$years < 0) stop("age must not be negative", call. = FALSE)
if (x$years > 150) stop("age is too large", call. = FALSE)
x
}
age <- function(years) validate_age(structure(list(years = as.double(years)), class = "age"))
for (input in c("30", "-2", "200")) {
result <- tryCatch(paste("ok", age(input)$years), error = function(e) conditionMessage(e))
cat(result, "\n")
}פלט:
ok 30
age must not be negative
age is too large לכל אחת משלוש הפונקציות יש תפקיד אחד. new_money() קפדנית ומהירה, ומיועדת לקוד שבו כבר נעשה שימוש בטיפוסים הנכונים. validate_money() מכילה את הכללים לגבי ערכים, שעשויים להיות איטיים לבדיקה או רבים. money() ידידותית, והיא הפונקציה שבה משתמש שאר התוכנית:
new_money() # טיפוסים בלבד; בונה את האובייקט באמצעות structure()
validate_money() # כללים לערכים; מפעיל stop() עם הודעה, אחרת מחזיר את x
money() # ממיר את הקלט, ואז מפעיל validate_money(new_money(...))אתגר
קלnew_score(points, max) בקובץ Score.R בונה אובייקט score. השלימו את הפונקציות האחרות באותו קובץ:
validate_score(x)עוצרת עםpoints must not be negative,max must be positiveאוpoints must not exceed max, לפי הסדר הזה, ואחרת מחזירה אתx.score(points, max = 100)ממירה את שני הארגומנטים באמצעותas.double()ומחזירהvalidate_score(new_score(...)).format.score(x, ...)מחזירה45/50 (90%), כשהאחוז מעוגל למספר שלם.
השתמשו ב-call. = FALSE בכל קריאה ל-stop(). הקוד שסופק קורא את השורה 45 50, מדפיס את הציון המעוצב, או את error: ואת הודעת השגיאה.
הקוד שלכם ייכתב ב-Score.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
source("Score.R")
# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
s <- tryCatch(score(p[1], p[2]), error = function(e) conditionMessage(e))
if (is.character(s)) cat("error: ", s, "\n", sep = "") else cat(format(s), "\n", sep = "")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות S3
עבודה עם קבציםרשימות עם מחלקהפונקציות בנאימתודות print ו-formatמאמתים ופונקציות עזרחזרה – טמפרטורותתרגלו בעצמכם: קומפיילר R אונליין