Closures כאובייקטים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 17 מתוך 57.
למדת על סגירות ב-Logic & Flow: פונקציה שנוצרת בתוך פונקציה אחרת שומרת את המשתנים שסביבה. מפעל פונקציות שמחזיר רשימה של פונקציות כאלה יוצר אובייקט. המשתנים המקומיים שלו הם הנתונים של האובייקט, והפונקציות הן המתודות שלו:
make_account <- function(balance = 0) {
deposit <- function(x) balance <<- balance + x
get_balance <- function() balance
list(deposit = deposit, get_balance = get_balance)
}
acc <- make_account(100)
acc$deposit(50)
print(acc$get_balance())פלט:
[1] 150כל קריאה לפונקציית המפעל מריצה שוב את הגוף שלה, ולכן לכל אובייקט יש משתנים משלו. שינוי של חשבון אחד אינו משפיע על האחר:
make_account <- function(balance = 0) {
list(deposit = function(x) balance <<- balance + x,
get_balance = function() balance)
}
ada <- make_account(100)
bo <- make_account(5)
ada$deposit(1)
cat(ada$get_balance(), bo$get_balance())פלט:
101 5הנתונים פרטיים. balance אינו איבר ברשימה, ולכן acc$balance הוא NULL והשמה אליו רק מוסיפה איבר לא קשור. הפונקציות ברשימה הן כל הממשק הציבורי של האובייקט:
make_account <- function(balance = 0) {
list(get_balance = function() balance)
}
acc <- make_account(100)
print(acc$balance)
acc$balance <- 1e6
print(acc$get_balance())פלט:
NULL
[1] 100המתודות יכולות לקרוא זו לזו כשהן מוגדרות כפונקציות מקומיות לפני בניית הרשימה. כאן add_many() משתמשת מחדש ב-add():
make_tally <- function() {
total <- 0
add <- function(x) total <<- total + x
add_many <- function(xs) for (x in xs) add(x)
get <- function() total
list(add = add, add_many = add_many, get = get)
}
t <- make_tally()
t$add(1)
t$add_many(c(2, 3, 4))
print(t$get())פלט:
[1] 10אתגר
קלהשלימו את הפונקציה ליצירת מונה make_counter(start = 0) בקובץ Counter.R. היא שומרת את הערך הנוכחי כפרטי ומחזירה רשימה עם ארבע פונקציות: increment() ו־decrement() משנות את הערך ב־1, reset() מחזירה אותו ל־start, ו־value() מחזירה אותו.
הקוד שסופק קורא את ערך ההתחלה, ואז פקודות +, - או reset, ומדפיס את הערך אחרי כל אחת מהן. בסוף הוא מדפיס את השמות ברשימה שהוחזרה, שצריכה להכיל רק את ארבע הפונקציות.
יש לכתוב את הקוד בקובץ Counter.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
source("Counter.R")
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
counter <- make_counter(as.numeric(input[1]))
for (cmd in input[-1]) {
if (cmd == "+") counter$increment()
if (cmd == "-") counter$decrement()
if (cmd == "reset") counter$reset()
cat(cmd, " -> ", counter$value(), "\n", sep = "")
}
cat("fields visible: ", paste(sort(names(counter)), collapse = ", "), "\n", sep = "")
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות S3
עבודה עם קבציםרשימות עם מחלקהפונקציות בנאימתודות print ו-formatמאמתים ופונקציות עזרחזרה – טמפרטורותתרגלו בעצמכם: קומפיילר R אונליין