オブジェクトとしての環境
CoddyのRジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 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] FALSEclass属性を持つ環境は、参照セマンティクスを持つ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チャレンジ
簡単在庫は、在庫を表す名前付き数値ベクトルである変数 items を1つ持つ、クラス inventory の環境です。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 = "")
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rオンラインコンパイラ