Nothing
swirl_out <- function(..., skip_before=TRUE, skip_after=FALSE) {
wrapped <- strwrap(str_c(..., sep = " "),
width = getOption("width") - 2)
mes <- str_c("| ", wrapped, collapse = "\n")
if(skip_before) mes <- paste0("\n", mes)
if(skip_after) mes <- paste0(mes, "\n")
Encoding(mes) <- "UTF-8"
message(mes)
}
# Takes a plain English name and turns it into a more proper
# file or directory name
make_pathname <- function(name) {
gsub(" ", "_", str_trim(name))
}
xfer <- function(env1, env2){
if(length(ls(env1))==0)return()
lapply(ls(env1), function(var)getAssign(var, env1, env2))
}
getAssign <- function(var, env1, env2){
assign(var, get(var, env1, inherits=FALSE), envir=env2)
}
cleanAdmin <- function(){
udat <- file.path(find.package("swirl"), "user_data", "swirladmin")
file.remove(dir(udat, pattern="*[.]rda", full.names=TRUE))
invisible()
}
mergeLists <- function(sourceList, destList){
for (n in names(sourceList)){
destList[[n]] <- sourceList[[n]]
}
return(destList)
}
# Evaluates a user's expression in a clean environment
# whose parent is a snapshot of the previous official
# environment, i.e., the same environment in which
# the user entered the expression. Any values required
# for evaluation will be found in the snapshot. Any variables
# changed or created by the expression will appear in the
# clean environment, even if nothing changes in the global.
#
# For example, if x already has the value c(1, 2, 3) and
# the user enters x <- c(1, 2, 3), nothing will change
# in the global environment, but x with the value c(1, 2, 3)
# will appear in the clean environment.
#
# In case the user's expression involves random numbers, the
# values of variables which appear in the clean environment
# are copied from the global environment.
#
# For example, if the user enters x <- rnorm(100), then
# evaluating the expression in a clean environment will create
# a variable named x, but it will have a different value
# than that created by the user.
#
safeEval <- function(expr, e){
e1 <- cleanEnv(e$snapshot)
ans <- list()
temp <- capture.output(
try(suppressMessages(suppressWarnings(eval(expr,e1))), silent=TRUE)
)
if(is(temp, "try-error"))return(ans)
for (x in ls(e1)){
if(exists(x,globalenv()))
ans[[x]] <- get(x,globalenv())
}
return(ans)
}
# Creates a clean environment whose parent is
# a snapshot of the official environment in an
# earlier state. The snapshot itself is given the
# same parent as the global environment, which will
# consist of loaded namespaces and packages.
#
# Environments in R are subject to reference semantics,
# i.e., all references refer to the same copy. Hence,
# the state of an environment cannot be saved for later
# comparison merely by creating a second reference. Any
# change in the environment will affect all references.
# Lists, however, have R's usual copy-on-modify semantics.
# If snapshot <- as.list(globalenv()), a subsequent change
# in the global environment will not cause a change in
# the list (with the exotic exception of environments
# contained in the global environment.)
#
# Clean environments can be used to detect variables
# changed or created by a user, as in function safeEval.
# They can also be used to check the correctness of
# a value computed by a user.
#
# For example, if the user enters x <- 2*x, then the
# value of x in the global environment will have changed,
# but if the expression is evaluated in a clean environment
# the value of x on the right will be found in the snapshot
# hence will be the same as that found by the user.
#
cleanEnv <- function(snapshot){
# clone of snapshot
pe <- if(length(snapshot) > 0){
as.environment(as.list(snapshot))
} else {
new.env()
}
parent.env(pe) <- globalenv()
# return new environment whose parent is pe
return(new.env(parent=pe))
}
# LESSON PACKAGE DEPENDENCY SUPPORT
# Load lesson package dependencies quietly
loadDependencies <- function(lesson_dir) {
depends <- file.path(lesson_dir, "dependson.txt")
if(file.exists(depends)) {
packages_as_chars <- setdiff(readLines(depends, warn=FALSE), "")
# If the dependson file is empty, then proceed with lesson
if(length(packages_as_chars) == 0) return(TRUE)
swirl_out(s()%N%"Attempting to load lesson dependencies...")
for(p in packages_as_chars) {
p <- gsub("^\\s+|\\s+$", "", p) # trim leading and trailing whitespace
if(suppressPackageStartupMessages(
suppressWarnings(
suppressMessages(require(p, character.only=TRUE, quietly=TRUE))))) {
swirl_out(s()%N%"Package", sQuote(p), s()%N%"loaded correctly!")
} else {
swirl_out(s()%N%"This lesson requires the", sQuote(p),
s()%N%"package. Would you like me to install it for you now?")
yn <- select.list(choices=c(s()%N%"Yes", s()%N%"No"), graphics=FALSE)
if(yn == s()%N%"Yes") {
swirl_out(s()%N%"Trying to install package", sQuote(p), s()%N%"now...")
install.packages(p, quiet=TRUE)
if(suppressPackageStartupMessages(
suppressWarnings(
suppressMessages(require(p,
character.only=TRUE,
quietly=TRUE))))) {
swirl_out(s()%N%"Package", sQuote(p), s()%N%"loaded correctly!")
} else {
swirl_out(s()%N%"Could not install package", paste0(sQuote(p), "!"))
return(FALSE)
}
} else {
return(FALSE)
}
}
}
}
# If loop completes, then print a blank line and return TRUE
cat("\n")
return(TRUE)
}
# Execute correct answers for rows 1 through 'up_through' of lesson
complete_part <- function(e) {
up_through <- e$test_from - 1
# Get rows though 'up_through' argument
les <- e$les[seq(up_through), ]
# Execute previous correct answers in global env
exec_cmd <- function(row) {
if(row['Class'] == "cmd_question") {
eval(parse(text = row['CorrectAnswer']), envir=globalenv())
} else if(row['Class'] == "script") {
orig_script_name <- row['Script']
correct_script_name <- paste0(
tools::file_path_sans_ext(orig_script_name), "-correct.R")
correct_script_path <- file.path(e$path, "scripts",
correct_script_name)
if(file.exists(correct_script_path)) {
try(source(correct_script_path))
} else {
stop("Correct script not found at ", correct_script_path)
}
}
}
message("Completing the first part of the lesson for you...\n")
apply(les, 1, exec_cmd)
invisible()
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.