Menu
Coddy logo textTech

Ambientes como Objetos

Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 18 de 57.

Um ambiente é um conjunto de valores nomeados, como uma lista, criado com new.env(). A diferença é que um ambiente nunca é copiado: toda variável que faz referência a ele vê o mesmo objeto, portanto uma alteração feita por meio de um nome fica visível por meio de todos eles:

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)

Saída:

[1] 99
[1] 1

Uma função que recebe um ambiente altera o objeto do chamador. Ela não precisa retornar nada, e o chamador não atribui um resultado:

deposit <- function(acc, x) acc$balance <- acc$balance + x
acc <- new.env()
acc$balance <- 10
deposit(acc, 5)
deposit(acc, 5)
print(acc$balance)

Saída:

[1] 20

assign(), get() e exists() funcionam com um nome armazenado em uma variável, e ls() lista os nomes em um ambiente em ordem classificada:

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))

Saída:

[1] "apple" "pear" 
[1] 4
[1] FALSE

Um ambiente com um atributo de classe é um objeto S3 com semântica de referência: seus métodos funcionam normalmente, e as funções que o modificam fazem isso no próprio objeto:

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

Saída:

wallet with 7 coins
challenge icon

Desafio

Fácil

Um inventário é um ambiente da classe inventory com uma variável, items, um vetor numérico nomeado de estoque. Complete Inventory.R:

  • new_inventory() cria o ambiente com um items vazio (c() serve) e a classe.
  • add_stock(inv, item, n) adiciona n ao estoque do item, começando em 0 para um item novo.
  • take_stock(inv, item, n) remove n e retorna TRUE quando há quantidade suficiente; caso contrário, não altera nada e retorna FALSE.
  • stock_of(inv, item) retorna o estoque, 0 para um item desconhecido.

As funções alteram o inventário diretamente e não o retornam. O código fornecido lê os comandos add apple 5 e take apple 2, imprime o resultado de cada take e, em seguida, cada item em ordem alfabética.

Seu código deve ficar em Inventory.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

source("Inventory.R")

# Código de entrada/saída fornecido: mantenha-o como está
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 = "")
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de R online