R/methods.R

#' @title Print generic for dict
#' @param x Object of type \code{dict}.
#' @param ... Additional arguments.
#' @examples
#' d <- dict(x = 1L, y = 3.14)
#' print(d)
#' # A dict of size 2
#' # x':  int 1
#' # y':  num 3.14
#'
#' \dontrun{
#' vals <- seq(1e4)
#' keys <- as.character(vals)
#' long_dict <- dict(keys, vals)
#' print(long_dict)
#' }
#' @export
print.dict <- function(x, ...) {
  if (x$is_empty()) {
    cat("empty dict container")
    return(invisible(x))
  }

  nb <- 5
  size <- x$size()
  cat(sprintf("A dict of size %s\n", size))

  for (it in x$items(n = nb)) {
    cat(paste0("'", it$key, "': "))
    str(it$value)
  }

  if (size > nb)
    cat(sprintf("... with %s more item(s)\n", size - nb))

  invisible(x)
}

#' @title Get items from a dict
#' @description This function simplifies iteration through
#' key/value pairs in \code{dict} (see examples).
#' @param d Object of type \code{dict}.
#' @return Items in \code{d}.
#' @examples
#' d <- dict(one = 1, two = 2, three = 3)
#' for (item in items(d))
#'   print(paste(item$key, "has value", item$value))
#'
#'\dontrun{
#' month_dict <- dict(month.name, seq_along(month.name))
#' for (item in items(month_dict))
#'   if (item$key == "May") print(item$value)
#'}
#' @export
items <- function(d) {
  stopifnot(class(d) == "dict")
  d$items()
}

#' @title Get keys from a dict
#' @param d Object of type \code{dict}.
#' @return Keys in \code{d}.
#' @examples
#' d <- dict(a = 1, b = 2)
#' keys(d)
#' @export
keys <- function(d) {
  stopifnot(class(d) == "dict")
  d$keys()
}

#' @title Get values from a dict
#' @param d Object of type \code{dict}.
#' @return Values in \code{d}.
#' @examples
#' d <- dict(x = TRUE, y = seq(1:10))
#' values(d)
#' @export
values <- function(d) {
  stopifnot(class(d) == "dict")
  d$values()
}

#' @title Generic for string representation
#' @param object Object of type \code{dict}.
#' @param ... Additional arguments.
#' @examples
#' d <- dict(x = 1, y = 2)
#' str(d)
#' # [s3 dict object]
#' @export
str.dict <- function(object, ...) {
  cat("[s3 dict object]\n")
}

#' @title Generic for length of dict
#' @param x Object of type \code{dict}.
#' @examples
#' d <- dict(a = 1, b = 2, c = "three")
#' length(d)
#' # [1] 3
#'
#' \dontrun{
#' letter_dict <- dict(keys = letters, values = seq_along(letters))
#' length(letter_dict)
#' # [1] 26
#' }
#' @export
length.dict <- function(x) {
  x$size()
}

#' Number of elements in a dict
#' @param d Object of class \code{dict}.
#' @return Number of elements in \code{d}.
#' @examples
#' d <- dict(a = 1, b = 2, x = seq(5))
#' size(d)
#' # [1] 3
#' @export
size <- function(d) {
  stopifnot(class(d) == "dict")
  d$size()
}

#' @title Prevents length assignment
#' @param x Object of class \code{dict}.
#' @param value Length to assign.
#' @return Throws an error (assigning length doesn't make sense in \code{dict}).
#' @examples
#' \dontrun{
#' d <- dict()
#' length(d) <- 2
#' }
#' @export
`length<-.dict` <- function(x, value) {
  stop("length<- opreation is not allowed for dict")
}

#' @title Create a list from x
#' @description When \code{x} is not a \code{list}, \code{as.list(x)} doesn't return the
#' same as \code{list(x)}. Hence this convenience wrapper.
#' @param x Object.
#' @return A \code{list}.
listify <- function(x) {
  if (length(x) && is.list(x)) x else list(x)
}

#' @title Extract or Replace Parts of a dict
#' @param x Object of class \code{dict}.
#' @param i,j Indices specifying elements to replace.
#' @param value Values to insert into \code{dict}.
#' @param name Character string or a name.
#' @examples
#' # Extracting keys
#' d <- dict(x = 1, y = 2)
#' d["x"]
#' d["z"] <- 3
#'
#' # Vectorized assignments
#' new_keys <- c("one", "two")
#' new_vals <- c(1, 2)
#' d[new_keys] <- new_vals
#'
#' d[[letters]] <- LETTERS
#' d[["a"]]
#' d[["B"]]
#'
#' # Vectorized extractions
#' keys_to_extract <- c("x", "two")
#' d[keys_to_extract] # return named list
#' d[[keys_to_extract]] # returns nameless list
#'
#' \dontrun{
#' d <- dict()
#' d$x <- 1 # will throw an error
#' d$x # NULL
#'
#' d[1] <- 1 # not allowed - key has to be a character
#' d["a"] <- c(1, 2) # will assign c(1, 2) to name 'a'
#' d[c("a", "b")] <- c(1, 2) # will assign 1 to 'a' and 2 to 'b'
#' d[c("a", "b", "c")] <- c(1, 2) # will throw an error
#' }
#' @rdname sub-dict
#' @export
`[.dict` <- function(x, i, j) {
  setNames(listify(x$get(i)), nm = i)
}

#' @rdname sub-dict
#' @export
`[[.dict` <- function(x, i, j) {
  x$get(i)
}

#' @rdname sub-dict
#' @export
`[<-.dict` <- function(x, i, j, value) {
  x$set(i, value)
  x
}

#' @rdname sub-dict
#' @export
`[[<-.dict` <- function(x, i, j, value) {
  x$set(i, value)
  x
}

#' @rdname sub-dict
#' @export
`$<-.dict` <- function(x, name, value) {
  stop("$<- assignment not possible in dict")
}
skubicius/dictionary documentation built on May 7, 2019, 7:17 p.m.