סביבות כאובייקטים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 18 מתוך 57.
סביבה היא אוסף של ערכים בעלי שמות, כמו רשימה, שנוצר באמצעות new.env(). ההבדל הוא שסביבה לעולם אינה מועתקת: כל משתנה שמפנה אליה רואה את אותו אובייקט, ולכן שינוי באמצעות שם אחד גלוי דרך כולם:
e <- new.env()
e$count <- 1
alias <- e
alias$count <- 99
print(e$count)
l <- list(count = 1)
copy <- l
copy$count <- 99
print(l$count)פלט:
[1] 99
[1] 1פונקציה שמקבלת סביבה משנה את האובייקט של הקורא לה. היא לא חייבת להחזיר דבר, והקורא לה לא מקצה תוצאה:
deposit <- function(acc, x) acc$balance <- acc$balance + x
acc <- new.env()
acc$balance <- 10
deposit(acc, 5)
deposit(acc, 5)
print(acc$balance)פלט:
[1] 20assign(), get() ו-exists() פועלות עם שם המאוחסן במשתנה, ו-ls() מציגה את שמות המשתנים בסביבה לפי סדר ממוין:
e <- new.env()
for (fruit in c("pear", "apple")) assign(fruit, nchar(fruit), envir = e)
print(ls(e))
print(get("pear", envir = e))
print(exists("kiwi", envir = e))פלט:
[1] "apple" "pear"
[1] 4
[1] FALSEסביבה עם מאפיין מחלקה היא אובייקט S3 בעל סמנטיקה של הפניה: המתודות שלו פועלות כרגיל, ופונקציות שמשנות אותו עושות זאת במקום:
new_wallet <- function(coins = 0) {
w <- new.env()
w$coins <- coins
class(w) <- "wallet"
w
}
print.wallet <- function(x, ...) {
cat("wallet with", x$coins, "coins\n")
invisible(x)
}
spend <- function(w, n) w$coins <- w$coins - n
w <- new_wallet(10)
spend(w, 3)
wפלט:
wallet with 7 coinsאתגר
קלמלאי הוא סביבה מהמחלקה inventory עם משתנה אחד, items, שהוא וקטור מספרי בעל שמות של פריטי מלאי. השלימו את Inventory.R:
new_inventory()יוצרת את הסביבה עםitemsריק (c()מתאים) ואת המחלקה.add_stock(inv, item, n)מוסיפהnלמלאי של הפריט, החל מ-0 עבור פריט חדש.take_stock(inv, item, n)מסירהnומחזירהTRUEכשיש מספיק, אחרת אינה משנה דבר ומחזירהFALSE.stock_of(inv, item)מחזירה את הכמות במלאי, 0 עבור פריט לא מוכר.
הפונקציות משנות את המלאי במקום ואינן מחזירות אותו. הקוד שסופק קורא פקודות add apple 5 ו-take apple 2, מדפיס את התוצאה של כל take, ואז את כל הפריטים בסדר אלפביתי.
יש לכתוב את הקוד שלך ב-Inventory.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
source("Inventory.R")
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
inv <- new_inventory()
for (line in input) {
p <- strsplit(line, " ")[[1]]
n <- as.numeric(p[3])
if (p[1] == "add") add_stock(inv, p[2], n)
if (p[1] == "take") cat("take ", p[2], ": ", if (take_stock(inv, p[2], n)) "ok" else "not enough", "\n", sep = "")
}
for (item in sort(names(inv$items))) cat(item, ": ", stock_of(inv, item), "\n", sep = "")
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות S3
עבודה עם קבציםרשימות עם מחלקהפונקציות בנאימתודות print ו-formatמאמתים ופונקציות עזרחזרה – טמפרטורותתרגלו בעצמכם: קומפיילר R אונליין