R primitives
# A name is just a tag by which we call objects, # for example, a = 4, a is the name. # In R, we have a name class, so when you evaluate a name object, you get its value. # You can also create a name by a string, and then eval. # The process is like: string "a" ... name a ... a a = 15.1567 aname = as.name("a") cat("class of aname: ", class(aname), "\n") cat("string presentation of aname: ", aname, "\n") cat("value of aname: ", eval(aname), "\n") # You can also get a name obj by the quote function: a = 15.1567 aname = quote(a) cat("class of aname: ", class(aname), "\n") cat("string presentation of aname: ", aname, "\n") cat("value of aname: ", eval(aname), "\n") # A call object is just an unevaluated call. # It can be built from a list. a = 15.1567 x = call("round", 15.1567) y = call("round", quote(a)) is.call(x) is.call(y) for(i in seq(x)) { cat(i, ": ") cat("class of x[[i]]: ", class(x[[i]]), "\n") cat("string presentation of x[[i]]: ", x[[i]], "\n") } for(i in seq(y)) { cat(i, ": ") cat("class of y[[i]]: ", class(y[[i]]), "\n") cat("string presentation of y[[i]]: ", y[[i]], "\n") } print(eval(x)) print(eval(y)) # An expression is simply a sequence of calls # you will find some similarity between expression and call: a = 1 b = 2 x = expression(a + b) y = call("+", a, b) cat("Get the result by expression: ", eval(x), "\n") cat("Get the result by call: ", eval(y), "\n") # More formally, an expression is a call of the form # (f, a1, ..., an), # which we normally read as # f(a1, ..., an). # Here `x[[1]]` is equivalent to # (sin, a+b+1) # or, more correctly, # (sin, (+, a, (+, b, 1))). # Thus, `x[[1]][2]` returns # ((+, a, (+, b, 1))) # (i.e. `(a+b+1)()` - no args!), and # `x[[1]][[2]]` gives # (+, a, (+, b, 1)), # i.e. `a+b+1`. # A longer expression, with two calls x = expression(sin(cos(a))) for(i in seq(x)) { cat(i, ": ") cat("class of x[[i]]: ", class(x[[i]]), "\n") cat("string presentation of x[[i]]: ", x[[i]], "\n") } x = 1 y = 2 z = 3 foo <- function(a, ...) { arg <- deparse(substitute(a)) # dots <- substitute(list(...))[-1] dots <- substitute(list(...)) print(class(dots)) print(dput(dots)) print(length(dots)) for(i in seq(dots)) { print(class(dots[[i]])) print(dots[[i]]) } # c(substitute(a), sapply(dots, deparse)) } foo(x, y, z) bar = function() { # for ordinary variable, its value is substituted # so basically, y = substitute(x) is equivalent to y = x x = 1.3 y = substitute(x) print(class(y)) print(y) # for ordinary variable, in this case a function, its value is substituted # so basically, y = substitute(x) is equivalent to y = x x = function() {cat("hihihi\n")} y = substitute(x) print(class(y)) print(y) y() } bar() # there is an exception for the above rule: # in the global frame, the symbol is left unchanged x = 1:3 y = substitute(x) print(class(y)) print(eval(y)) f = function() cat("nobody\n") bar = function(a = f) { # due to lazy evaluation, a is called a "promise object" # when a is a promise, substitute replaces it with its expression slot, i.e. f b1 = substitute(a) print(class(b1)) b2 = eval(substitute(a)) print(class(b2)) b2() } bar()
0 comments:
Post a Comment