Skip to content

Instantly share code, notes, and snippets.

@hadley
Created August 30, 2018 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hadley/3a8dc7fd539615d2868ceb31baaa6c59 to your computer and use it in GitHub Desktop.
Save hadley/3a8dc7fd539615d2868ceb31baaa6c59 to your computer and use it in GitHub Desktop.
# Constructor and basic methods ---------------------------------------------
new_rational <- function(n, d) {
stopifnot(is.integer(n), is.integer(d))
stopifnot(length(n) == length(d))
structure(list(d = d, n = n), class = "rational")
}
length.rational <- function(x) {
length(x$d)
}
`[.rational` <- function(x, i) {
new_rational(x$n[i], x$d[i])
}
# "Scalar" is just length one vector
`[[.rational` <- function(x, i) {
new_rational(x$n[[i]], x$d[[i]])
}
print.rational <- function(x, ...) {
cat("<rational[", length(x), "]>\n", sep = "")
if (length(x) > 0 )
print(paste0(x$n, "/", x$d), quote = FALSE)
invisible(x)
}
r <- new_rational(c(1L, 1L), c(2L, 3L))
r
r[0]
r[c(2:1, 1)]
r[[1]]
# Names -------------------------------------------------------------------
# But what should names() and $ do?
# length(names(x)) must either be 0 (i.e. NULL) or length(x)
# so it can't be "d", "n". I think the easiest solution is to say:
names.rational <- function(x) {
names(x$n)
}
r2 <- new_rational(c(a = 1L, b = 2L), c(4L, 6L))
r2
# We need a better print method
print.rational <- function(x, ...) {
cat("<rational[", length(x), "]>\n", sep = "")
if (length(x) > 0 )
print(setNames(paste0(x$n, "/", x$d), names(x$n)), quote = FALSE)
invisible(x)
}
r2
# [[ ----------------------------------------------------------------------
# Presumably r2["a"] should be equivalent to r2[1], and r2[["a"]] to r2[[1]]
`[.rational` <- function(x, i) {
nms <- setNames(seq_along(x), names(x))
idx <- nms[i]
new_rational(x$d[idx], x$n[idx])
}
`[[.rational` <- function(x, i) {
nms <- setNames(seq_along(x), names(x))
idx <- nms[[i]]
new_rational(x$d[[idx]], x$n[[idx]])
}
r2[["a"]]
r2[c("b", "a")]
# And x$y should be equivalent to x[["y"]]
# But the naive approach doesn't work because we've previously relied
# on $ indexing into the list
`$.rational` <- function(x, name) {
nms <- setNames(seq_along(x), names(x))
idx <- nms[[name]]
new_rational(x$d[[idx]], x$n[[idx]])
}
# So we need to use .subset2() everywhere
names.rational <- function(x) {
names(.subset2(x, "n"))
}
length.rational <- function(x) {
length(.subset2(x, "n"))
}
`$.rational` <- function(x, name) {
nms <- setNames(seq_along(x), names(x))
idx <- nms[[name]]
new_rational(.subset2(x, "d")[[idx]], .subset2(x, "n")[[idx]])
}
print.rational <- function(x, ...) {
cat("<rational[", length(x), "]>\n", sep = "")
if (length(x) > 0 )
print(setNames(paste0(.subset2(x, "n"), "/", .subset2(x, "d")), names(.subset2(x, "n"))), quote = FALSE)
invisible(x)
}
r2$a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment