Exercises are interactive R code chunks that allow readers to directly execute R code and see it’s results. There are many options associated with tutorial exercises (all of which are described in more detail below):

Option Description
exercise.cap Caption for exercise chunk (defaults to “Code”)
exercise.eval Whether to pre-evaluate the exercise so the reader can see some default output (defaults to FALSE).
exercise.lines Lines of code for exercise editor (default to size of code chunk).
exercise.timelimit Number of seconds to limit execution time to (defaults to 30).
exercise.checker Function used to check exercise answers.
exercise.completion Whether to enable code completion in the exercise editor.
exercise.diagnostics Whether to enable code diagnostics in the exercise editor.
exercise.startover Whether to include a “Start Over” button for the exercise.

Note that these options can all be specified either globally or per-chunk. For example, the following code sets global default options using the setup chunk and also sets some local options on the addition chunk:

There are also some other specialized chunks that can be used with an exercise chunk, including:

  1. Exercise setup chunks, which enable you to execute code to setup the environment immediately prior to executing submitted code.

  2. Exercise solution chunks which enable you to provide a solution to the exercise that can be optionally viewed by users of the tutorial.

The use of these special chunks is also described in detail below.

Exercise Evaluation

By default, exercise code chunks are NOT pre-evaluated (i.e there is no initial output displayed for them). However, in some cases you may want to show initial exercise output (especially for exercises like the ones above where the user is asked to modify code rather than write new code from scratch).

You can arrange for an exercise to be pre-evaluated (and it’s output shown) using the exercise.eval chunk option. This option can also be set either globally or per-chunk:

Exercise Setup

Code chunks with exercise=TRUE are evaluated within standalone environments. This means that they don’t have access to previous computations from within the document. This constraint is imposed so that users can execute exercises in any order (i.e. correct execution of one exercise never depends on completion of a prior exercise).

You can however arrange for setup code to be run before evaluation of an exercise to ensure that the environment is primed correctly. There are three ways to provide setup code for an exercise:

  1. Add code to the global setup chunk. This code is run once at the startup of the tutorial and is shared by all exercises within the tutorial. For example:

  2. Create a setup chunk that’s shared by several exercises. If you don’t want to rely on global setup but would rather create setup code that’s used by only a handful of exercises you can use the exercise.setup chunk attribute to provide the label of another chunk that will perform setup tasks. To illustrate, we’ll re-write the previous example to use a shared setup chunk named prepare-flights:

  3. Create a setup chunk that’s specific to another chunk using a -setup chunk suffix. To do this give your exercise chunk a label (e.g. filter) then add another chunk with the same label plus a -setup suffix (e.g. filter-setup). For example:

Hints and Solutions

You can optionally provide a hint or solution for each exercise that can be optionally displayed by users. Hints can be based on either R code snippets or on custom markdown/HTML content.

R Code Hints

To create a hint or solution based on R code simply create a new code chunk with “-hint” or “-solution” chunk label suffix. For example:

A “Hint” or “Solution” button is added to the left side of the exercise header region:

Markdown Hints

To create a hint based on custom markdown content simply add a <div> tag with an id attribue that marks it as hint for your exercise (e.g. “filter-hint”). For example:

The content within the <div> will be displayed underneath the R code editor for the exercise whenever the user presses the “Hint” button.

Multiple Hints

For R code hints you can provide a sequence of hints that reveal progressively more of the solution as desired by the user. To do this create a sequence of indexed hint chunks (e.g. “-hint-1”, “-hint-2,”-hint-3“, etc.) for your exercise chunk. For example:

Progressive Reveal

You might want users of your tutorials to see only one sub-topic at a time as they work through the material (this can be helpful to reduce distractions and maintain focus on the current task). If you specify the progressive option then all Level 3 headings (###) will be revealed progressively. For example:

You can also specify this option on a per topic basis using the data-progressive attribute. For example, the following code enables progressive rendering for a single topic:

You can also use data-progressive=FALSE to disable progressive rendering for an individual topic if the global progressive option is TRUE.

Progressive reveal provides an easy way to cue exercises one at a time: place each exercise under its own Level 3 header (###). This can be useful when a second exercises builds on the first, giving away the answer to the first.

Note that this feature is only available if you are using the learnr::tutorial R Markdown format (other custom formats may have their own internal mechanisms for progressive reveal).

Exercise Skipping

When the progressive option is set to true, the tutorial will require students to complete any exercises in a sub-section before advancing to the next sub-section.

You may want to allow users of your tutorials to skip through exercises that they can’t quite figure out. This might especially be true if you want users to be able to optionally see the next exercise even if they haven’t completed the prior one.

If you specify the allow_skip option then students will be able to advance through a sub-section without completing the exercises. For example:

You can also specify this option on a per sub-topic basis using the data-allow-skip attribute. For example, the following code enables exercise skipping within a single sub-topic:

You can also use data-allow-skip=FALSE to disable exercise skipping rendering for an individual sub-topic if the global allow-skip option is TRUE.

Exercise Checking

The learnr package doesn’t directly include features for checking exercise inputs however it does include lower-level hooks that enable other packages to provide tools for exercise checking. You can provide an external function for exercise checking by setting the exercise.checker knitr chunk option within the setup chunk of your tutorial, then adding a “-check” chunk for any exercise you want to check. For example:

When you provide a “-check” chunk for an exercise, an additional “Submit Answer” button is added to the exercise editor:

This is provided so that users can experiment with various solutions before formally submitting an answer they believe is correct.

Checker Function

What the code within the “-check” chunk actually does will vary depending on which exercise checker is currently active. The exercise checker function is passed various arguments which provide the context required to check the user’s exercise input:

Argument Description
label Label for exercise chunk.
user_code R code submitted by the user.
solution_code Code provided within the “-solution” chunk for the exercise.
check_code Code provided within the “-check” chunk for the exercise.
envir_result The R environment after the execution of the chunk.
evaluate_result The return value from the evaluate::evaluate function.
Unused (include for compatibility with parameters to be added in the future)

The checker function should return an R list which contains several fields indicating the result of the check. For example:

The fields within this list and their valid values include:

Field Description
message Feedback message. Can be a plain character vector or can HTML produced via the htmltools package.
correct TRUE/FALSE logical value indicating whether the submitted answer was correct.
type Feedback type (visual presentation style). Can be “auto”, “success”, “info”, “warning”, “error”, or “custom”. Note that “custom” implies that the “message” field is custom HTML rather than a character vector.
location Location for feedback (“append”, “prepend”, or “replace”).

Code Checking

You can also choose to check the user’s code prior to it being submitted to R. To do this, include a “-code-check” chunk in addition to a “-check” chunk. The checker function will be called prior to the execution of the chunk with the envir_result and evaluate_result parameters set to NULL. If it returns “incorrect” feedback it is displayed and R code chunk is not executed.

Here’s how we’d update the example checking function to also perform code checking:

Here the is_bad_code function is a proxy for whatever logic your code checking provides to validate user source code.

Checking Packages

The checkr package currently provides code checking functions that are compatible with learnr.

We expect that additional learnr compatible checking packages will be developed and will update this section as they become available.

Exercise Caption

By default exercises are displayed with caption of “Code”. However, in some cases you may want either a custom per-chunk caption or a generic caption with a different connodation (e.g. “Exercise” or Sandbox“). For example:

Code Assistance

By default, code completions are automatically provided as users type within the exercise editor:

You can optionally disable code completion (either globally or on a per-chunk basis) using the exercise.completion option. For example, the following illustrates turning off completions globally then enabling them for an individual chunk:

Similarily, simple code diagnostics can also be provided, to inform users of errors in the R code written in exercise editors. Diagnostics can be controlled (either globally or on a per-chunk basis) using the exercise.diagnostics option.

Editor Size

By default, the size of the exercise editor provided to users will match the number of lines in your code chunk (with a minimum of 2 lines). If the user adds additional lines in the course of editing the editor will grow vertically up to 15 lines, after which it will display a scrollbar.

You can also specify a number of lines explicitly using the exercise.lines chunk option (this can be done on a per-chunk or global basis). For example, the following chunk specifies that the exercise code editor should be 15 lines high:

Time Limits

To mediate the problem of code which takes longer than expected to run you can specify the exercise.timelimit chunk option or alternatively the global tutorial.exercise.timelimit option.

The following demonstrates setting a 10 second time limit as a global option, document level option, and chunk level option:

Since tutorials are a highly interactive format you should in general be designing exercises that take no longer than 5 or 10 seconds to execute. Correspondingly, the default value for tutorial.exercise.timelimit if not otherwise specified is 30 seconds.