Writing programs (or code) that can manipulate other programs (or code).
Writing programs (or code) that can manipulate other programs (or code).
Does metaprogamming == Non Standard Evaluation (NSE)?
[Metaprogramming] is the idea that code is data that can be inspected and modified programmatically... Closely related to metaprogramming is non-standard evaluation, NSE for short. This term, which is commonly used to describe the behaviour of R functions, is problematic.. NSE is actually a property of the argument (or arguments) of a function, so talking about NSE functions is a little sloppy.
References: (1) https://rstudio.com/resources/rstudioconf-2018/tidy-eval-programming-with-dplyr-tidyr-and-ggplot2/, (2) https://www.youtube.com/watch?v=nERXS3ssntw, (3) https://www.youtube.com/watch?v=g1h-YDWVRLc
But what does that mean???
But what does that mean???
"R code can be described as expressions, which can be drawn as trees."
An expression is anything that has a value. The simplest expressions are literal values like the number 1, the string "stuff", and the Boolean TRUE. A variable like least is also an expression: its value is whatever the variable currently refers to. Complex expressions are built out of simpler expressions:
1 + 2
is an expression that uses+
to combine 1 and 2, while the expressionc(10, 20, 30)
uses the functionc
to create a vector out of the values 10, 20, 30. Expressions are often drawn as trees.
But what does that mean???
"R code can be described as expressions, which can be drawn as trees."
An expression is anything that has a value. The simplest expressions are literal values like the number 1, the string "stuff", and the Boolean TRUE. A variable like least is also an expression: its value is whatever the variable currently refers to. Complex expressions are built out of simpler expressions:
1 + 2
is an expression that uses+
to combine 1 and 2, while the expressionc(10, 20, 30)
uses the functionc
to create a vector out of the values 10, 20, 30. Expressions are often drawn as trees.
lobstr::ast(f(x, 'y', 1))
## o-f ## +-x ## +-"y" ## \-1
But what does that mean???
"R code can be described as expressions, which can be drawn as trees."
An expression is anything that has a value. The simplest expressions are literal values like the number 1, the string "stuff", and the Boolean TRUE. A variable like least is also an expression: its value is whatever the variable currently refers to. Complex expressions are built out of simpler expressions:
1 + 2
is an expression that uses+
to combine 1 and 2, while the expressionc(10, 20, 30)
uses the functionc
to create a vector out of the values 10, 20, 30. Expressions are often drawn as trees.
lobstr::ast(f(x, 'y', 1))
## o-f ## +-x ## +-"y" ## \-1
Colours will be shown when you call
ast()
, but do not appear in the book for complicated technical reasons.
But what does that mean???
"R code can be described as expressions, which can be drawn as trees."
An expression is anything that has a value. The simplest expressions are literal values like the number 1, the string "stuff", and the Boolean TRUE. A variable like least is also an expression: its value is whatever the variable currently refers to. Complex expressions are built out of simpler expressions:
1 + 2
is an expression that uses+
to combine 1 and 2, while the expressionc(10, 20, 30)
uses the functionc
to create a vector out of the values 10, 20, 30. Expressions are often drawn as trees.
lobstr::ast(f(x, 'y', 1))
## o-f ## +-x ## +-"y" ## \-1
Colours will be shown when you call
ast()
, but do not appear in the book for complicated technical reasons.
But what does that mean???
"R code can be described as expressions, which can be drawn as trees."
An expression is anything that has a value. The simplest expressions are literal values like the number 1, the string "stuff", and the Boolean TRUE. A variable like least is also an expression: its value is whatever the variable currently refers to. Complex expressions are built out of simpler expressions:
1 + 2
is an expression that uses+
to combine 1 and 2, while the expressionc(10, 20, 30)
uses the functionc
to create a vector out of the values 10, 20, 30. Expressions are often drawn as trees.
lobstr::ast(f(x, 'y', 1))
## o-f ## +-x ## +-"y" ## \-1
Colours will be shown when you call
ast()
, but do not appear in the book for complicated technical reasons.
Everything is a tree!
Everything is a tree!
Assignment and infix operator (*
)
x <- 1lobstr::ast(y <- 2 * x)
## o-`<-` ## +-y ## \-o-`*` ## +-2 ## \-x
Control flow statements
lobstr::ast(if(x > 1) y else x)
## o-`if` ## +-o-`>` ## | +-x ## | \-1 ## +-y ## \-x
Everything is a tree!
Assignment and infix operator (*
)
x <- 1lobstr::ast(y <- 2 * x)
## o-`<-` ## +-y ## \-o-`*` ## +-2 ## \-x
Control flow statements
lobstr::ast(if(x > 1) y else x)
## o-`if` ## +-o-`>` ## | +-x ## | \-1 ## +-y ## \-x
Functions
lobstr::ast(function(x, y) x + y)
## o-`function` ## +-o-x = `` ## | \-y = `` ## +-o-`+` ## | +-x ## | \-y ## \-<inline srcref>
ASTs
lobstr::ast(lobstr::ast(x + y))
## o-o-`::` ## | +-lobstr ## | \-ast ## \-o-`+` ## +-x ## \-y
ex1 <- rlang::expr(x + y)ex1
## x + y
ex1 <- rlang::expr(x + y)ex1
## x + y
x <- 1y <- 2eval(ex1)
## [1] 3
lobstr::ast(1 + 2)
## o-`+` ## +-1 ## \-2
rlang::expr
vs. rlang::enexpr
rlang::expr
vs. rlang::enexpr
rlang::expr
quotes your expression
f1 <- function(z) expr(z)f1(a + b)
## z
rlang::expr
vs. rlang::enexpr
rlang::expr
quotes your expression
f1 <- function(z) expr(z)f1(a + b)
## z
enexpr
quotes user's expression
f2 <- function(z) enexpr(z)f2(a + b)
## a + b
rlang::expr
vs. rlang::enexpr
rlang::expr
quotes your expression
f1 <- function(z) expr(z)f1(a + b)
## z
enexpr
quotes user's expression
f2 <- function(z) enexpr(z)f2(a + b)
## a + b
en
= "enriched"
mean(x + y)
library(ggplot2)
# ggplot(mtcars, aes(disp, mpg)) + geom_point()
mtcars$disp
z <- x + 1
data.frame(z = 3)
Blue: Evaluated using usual R rules
Red: Quoted and evaluated with special rules
lobstr::ast(eval(!!ex1))
## o-eval ## \-o-`+` ## +-x ## \-y
lobstr::ast(eval(!!ex1))
## o-eval ## \-o-`+` ## +-x ## \-y
ex2 <- rlang::expr(x / !!ex1)ex2
## x/(x + y)
lobstr::ast(eval(!!ex1))
## o-eval ## \-o-`+` ## +-x ## \-y
ex2 <- rlang::expr(x / !!ex1)ex2
## x/(x + y)
eval(ex2)
## [1] 0.3333333
lobstr::ast(eval(!!ex1))
## o-eval ## \-o-`+` ## +-x ## \-y
ex2 <- rlang::expr(x / !!ex1)ex2
## x/(x + y)
eval(ex2)
## [1] 0.3333333
lobstr::ast(eval(!!ex2))
## o-eval ## \-o-`/` ## +-x ## \-o-`+` ## +-x ## \-y
Understanding how to build code trees == success in online arguments.
Understanding how to build code trees == success in online arguments.
Understanding how to build code trees == success in online arguments.
Understanding how to build code trees == success in online arguments.
x <- 8 / 2 * (2 + 2)
lobstr::ast(x <- 8 / 2 * (2 + 2))
## o-`<-` ## +-x ## \-o-`*` ## +-o-`/` ## | +-8 ## | \-2 ## \-o-`(` ## \-o-`+` ## +-2 ## \-2
x
## [1] 16
quosure == closure + quote
quosure == closure + quote
Quosures aremportant for disambiguating the context in which expressions are evaluated (e.g. a column in a data frame or a variable in the parent environment).
Result is tibble(x = 0, y = 1)
.
update <- function(df, col) {
n <- 1
col <- rlang::enexpr(col)
res <- dplyr::mutate(df, y = !!col)
res
}
df <- tibble::tibble(x = 0)
n <- 2
update(df, x + n)
Result is tibble(x = 0, y = 2)
.
update <- function(df, col) {
n <- 1
col <- rlang::enquo(col)
res <- dplyr::mutate(df, y = !!col)
res
}
df <- tibble::tibble(x = 0)
n <- 2
update(df, x + n)
Metaprogramming is awesome. R is great because of how much control it allows user to have.
Metaprogramming is awesome. R is great because of how much control it allows user to have.
Chapter 18: More about R code as a tree
Chapter 19: More about evaluating (quoting) unevaluated code
Chapter 20: More about evaluating (unquoting) captured code
Understanding how "code is a tree" would have helped me with my final project in my Intro to Programming class.
Understanding how "code is a tree" would have helped me with my final project in my Intro to Programming class.
Please note that whether you choose to explicitly build a parse tree or not, you will almost certainly have to write your parsing and executing function(s) using recursion. Fortunately, the recursion required to do this is super easy (whether you build a parse tree or not, the recursion is very natural).
Implementing a Parse Tree is optional for Phase A. In Phase B, we will almost certainly mandate that you have a Parse Tree, and for Phase B, the parse trees are decidedly more complicated, since you will have both Expressions to represent and Statements to represent.
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |