rstudio / parsons

Create parsons problems to teach programming in learnr tutorials
http://rstudio.github.io/parsons/
Other
19 stars 5 forks source link

API design: use pass_if() and fail_if() #3

Open andrie opened 5 years ago

andrie commented 5 years ago

Intent: use a similar API to the grader project, as described in https://github.com/rstudio-education/grader/issues/11

In a nutshell, you should be able to write:

For both pass_if() and fail_if(), support:

```{r iris, echo=FALSE}
question_parsons(
  initial = c(
    "iris",
    "mutate(...)",
    "summarize(...)",
    "print()"
  ),
  pass_if(
    c(
      "iris",
      "mutate(...)",
      "summarize(...)"
    )
  ),
  pass_if(...),
  fail_if(
    ~length(.) < 2,
    message = "Include at least two answers"
  ),
  fail_if(
    function(x){"print()" %in% x},
    message = "You should not include print() in your answer"
  ),
  fail_if(
    function(x){x[1] != "iris"},
    message = "Your solution should start with 'iris'"
  )
)
andrie commented 5 years ago

@hadley suggests we make it possible to provide R code as the value for initial, and provides this sample code to parse the AST:

library(rlang)

parsonize <- function(x) {
  x <- enexpr(x)

  if (is.character(x)) {
    # Literal character string, so split up into lines, using glue's
    # triming algorithm to remove leading whitespace
    strsplit(glue::trim(x), "\n")[[1]]
  } else if (is.call(x)) {
    depipe(x)
  } else {
    abort("`x` must be a string or a function call.")
  }
}

# Returns a character vector
depipe <- function(x) {
  if (is_call(x, "+", 2) || is_call(x, "%>%", 2)) {
    c(depipe(x[[2]]), depipe(x[[3]]))
  } else {
    expr_text(x)
  }
}

parsonize("
  a + 
    b + 
    c
  ")

parsonize(a + b + c)
parsonize(a %>% b %>% c(d + e))