knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

Intro

We are happy to announce that version 0.11.0 of learnr has arrived at a CRAN mirror near you. This release collects many large and small improvements to the learnr package, all with the goal of making it easier to create interactive tutorials for teaching programming concepts and skills.

Read on for an overview of the changes in version 0.11.0, or review the changelog for a full list of updates. Use install.packages() to install the latest version of learnr, which includes demonstrations of many of the new features.

install.packages("learnr")

learnr speaks more than R

learnr tutorials are a great way to teach others R: it's in the package name, after all. And thanks to R Markdown's flexibility, learnr is a great way to teach other programming languages as well, using the spoken language of your choice!

Internationalization

learnr now allows tutorial authors to choose the words or language used for learnr's UI elements using the language argument of the tutorial format. We are very grateful for the contributions of a number of community members to allow learnr to include out-of-the-box support for the following languages:

```{=html}

You can choose one of the above via the `language` setting in your tutorial's YAML frontmatter:

output: learnr::tutorial: language: es runtime: shinyrmd


The language chosen for the tutorial is passed to the R session used to evaluate exercise code,
so that translatable messages from R will also be presented in the specified language
(thanks [Alex Rossell Hayes](https://github.com/rossellhayes)).

In addition, you can customize the words displayed on specific UI elements using a named list.
For example, the default text used on the "Run Code" button in Spanish is *Ejecutar código*.
You can use the Spanish language translation and modify this particular translation using a named list:

```
---
output:
  learnr::tutorial:
    language: 
      es:
        button:
          runcode: Ejecutar
runtime: shinyrmd
---

You can learn more about internationalization features and the full syntax for customizing the language used by learnr in the internationalization vignette.

We would love to support more languages and would happily welcome your contribution.

Support for additional programming languages

In addition to spoken languages, learnr is now better at running code in programming languages other than R. The biggest improvement is for SQL exercises, where learners can execute SQL queries on a database. This was previously possible, but now tutorial authors can use grading packages like gradethis to grade the tables returned by the student's queries. You can see this in action using run_tutorial("sql-exercise", "learnr") (SQL demo online version).

learnr also includes UI improvements in the interactive exercise component for other languages, including syntax highlighting and basic auto-completion for exercise code in languages such as Python, JavaScript, Julia and SQL. Try run_tutorial("polyglot", "learnr") (polyglot online version) to see several programming languages in use in the same tutorial.

```{=html} <img src = "images/r-python-exercise.png" alt="One R and one Python interactive exercise component, with the same source code but which evaluates differently in each language. The code is:

x = 5 x <- 10 print(x)" />

For exercise checking,
learnr communicates the exercise engine to exercise-checking functions
via a new `engine` argument that should be included in the exercise checker function signature.

## Exercises

Beyond expanded language support,
interactive exercises and questions in learnr tutorials
have received a number of updates and improvements.

### Setup chunk chaining

Thanks to [Nischal Shrestha](https://github.com/nischalshrestha),
exercises can now be chained together via chained setup chunks
such that the setup of one exercise may depend on other exercises[^1],
including the setup chunks of other exercises in the tutorial.
This makes it easier for the author to progressively work through a problem
with a series of interactive exercises that build on each other.

[^1]: Note that with chained setup chunks, an exercise only ever uses the code as written in the chunks in the source document. Exercises are still completely independent of each other when viewed by a user.

An exercise chunk 
an R chunk with `exercise = TRUE` 
can specify its setup chunk using the `{label}-chunk` naming convention
or with the `exercise.setup` chunk option.
Any chunk being used as a setup chunk may also include
an `execise.setup` option specifying its own parent chunk.

Try 
`run_tutorial("setup-chunks", "learnr")`
([setup-chunks online version](https://learnr-examples.shinyapps.io/setup-chunks/))
to see chained setup chunks in action.

### Catching common code issues

When teaching new programming concepts,
it can be helpful to provide learners with some scaffolding in an exercise
to focus their attention on skills they just recently learned.

For example, if you are explaining the difference between
the `names_from` and `values_from` arguments in `tidyr::pivot_wider()`,
you might want to ask students to practice using the arguments
without distracting them with writing code to set up a transformation.
It's common to use underscores or other patterns
to indicate that students should fill in a missing piece.

```r
library(tidyverse)

us_rent_income %>% 
  select(name = NAME, variable, estimate) %>%
  pivot_wider(names_from = ____, values_from = ____)

If students submit code containing blanks, learnr will warn the student that they should replace the ____ with valid code.

```{=html} A learnr exercise box with the feedback from submitting the code above. A red callout says "This exercise contains 2 blanks. Please replace ____ with valid code."

Blanks are detected using regular expressions (since blanks may make the code unparsable),
and learnr's default pattern is to detect three or more consecutive underscores.
Authors can choose the pattern for detecting blanks with the `exercise.blanks` chunk option.
Setting `exercise.blanks = "[.]{2}[a-z]+[.]{2}"`, for example,
would allow the author to use valid R syntax for blanks.
The warning message shown to students calls out the blanks they need to fill in.

```{=html}
<img src="images/blanks-warning-custom.png" alt="A learnr exercise box with the feedback from submitting the example code with a custom exercise.blanks pattern. A red callout says &quot;This exercise contains 2 blanks. Please replace '..names..' and '..values..' with valid code.&quot;" />

Another common problem in code involves character conversions when a student copies code from an application with automatic formatting and pastes the text into a learnr tutorial. We frequently see problems with quotation marks in code samples being converted to Unicode-formatted quotation marks (curly quotes). In general, these kinds of conversions make the R code unparsable. Now learnr will detect these mistakes and suggest a replacement.

```{=html} <img src="images/fancy-quotes-warning.png" alt="A learnr exercise box where the student's code contains curly quotes. The feedback message reads

It looks like your R code contains specially formatted quotation marks or "curly" quotes (“) around character strings, making your code invalid. R requires character values to be contained in straight quotation marks (" or ').

1: c(“hello”, “world”)

Don't worry, this is a common source of errors when you copy code from another app that applies its own formatting to text. You can try replacing the code on that line with the following. There may be other places that need to be fixed, too.

c("hello", "world") " />

Finally, if the learner submits code that isn't parsable --
and not for any of the above reasons --
learnr now returns a generic, but helpful,
feedback message
with guidance about common syntax errors.

```{=html}
<img src="images/syntax-warning.png" alt="A learnr exercise box where the student's code contains invalid R code. The feedback message reads:

It looks like this might not be valid R code. R cannot determine how to turn your text into a complete command. You may have forgotten to fill in a blank, to remove an underscore, to include a comma between arguments, or to close an opening &quot;, ', ( or { with a matching &quot;, ', ) or }." />

In all of the above cases, the actual R output, often an error message, is always shown to the learner. This helps students acclimate to the error messages they would see in their console if encountered in their every-day usage of R.

Improved keyboard support

Keyboard navigation and shortcuts for the interactive exercise code editor has been improved. Previously, the editor would trap keyboard focus because the Tab key is used for indentation in the editor. Now, users can press Escape when the editor has focus to temporarily disable using Tab for indentation, making it possible to move to the next or previous element in the tutorial.

```{=html}

A demonstration of navigating through an exercise editor. At the start of the animation, the editor has focus and '2 + 2' is typed into the editor. Then the user presses the Esc key and a dark outline is applied to the editor container. Pressing Shift and Tab moves to the previous element, the 'Run Code' button in the exercise toolbar. Then the user uses Tab to move back into the editor and again presses Esc to disable indentation, followed by Tab to move out of the editor to the next focusable element in the page.

The exercise editor also supports a few additional keyboard shortcuts:

* The (magrittr) pipe `%>%` with <kbd>Cmd</kbd> / <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd>

* The assignment arrow, `<-` with <kbd>Opt</kbd> / <kbd>Alt</kbd> + <kbd>-</kbd>

* <kbd>Cmd</kbd> / <kbd>Ctrl</kbd> + <kbd>Enter</kbd> runs the selected code


### The `data` directory

When users submit code as part of an exercise,
learnr evaluates their code in a temporary directory
that's used just for the evaluation of their submission.
This helps ensure that every submission returns the same value,
but it makes it harder for authors to write exercises that use files,
such as `.csv` or other files,
as inputs for the user's code.

To remedy this,
thanks to work by [Alex Rossell Hayes](https://github.com/rossellhayes),
learnr now treats a `data/` directory,
stored adjacent to the tutorial,
as special.
Authors can reference files in the `data/` directory
in the static content of tutorials,
and the files are also made available for student use in the exercises.
Each exercise evaluation copies the directory into the exercise's temporary directory
so that subsequent submissions work
even if the student accidentally overwrites or deletes
the files.
In all cases,
files in `data/` can be referenced
using the same relative path,
e.g. `"data/estimates.csv"`.

### Error checking

It is now possible to provide customized feedback
when a learner's exercise submission produces an evaluation error.
The `exercise.error.checker` option of `tutorial_options()`
allows authors to define an error-checking function that is applied
when an error is thrown by a user's code.
You may also use `exercise.error.check.code` to define the default error checking code
that would normally be written in an `-error-check` chunk.

An excellent default error checker is `gradethis::gradethis_error_checker()`,
which is enabled by default if [gradethis] is loaded in a learnr tutorial.
The gradethis error checker automatically provides the student with a hint
when an error is encountered,
by comparing the submitted code with the expected solution.

```{=html}
<img src="images/error-checker.png" alt="A learnr exercise box where the student's code results in an error. The submitted code is 'runif(max = 10)' and the feedback message reads

Your call to 'runif()' should include &quot;n&quot; as one of its arguments. You may have misspelled an argument name, or left out an important argument. That's okay: you learn more from mistakes than successes. Let's do it one more time." />

Questions

This release of learnr includes a new question type, question_numeric(). The numeric question type is a complement to question_text() when a numeric answer is required.

{=html} <img src="images/question-numeric.png" alt="A learnr question input asking &quot;What is pi rounded to 2 digits?&quot; followed by an input box with the text &quot;3.14&quot;" />

In general, question answers are specified with the answer() function, but these answers can only be a single value, which has limited applicability in text and numeric questions.

Now, authors can use answer_fn() to provide a single-argument function that takes the student's submitted answer and determines if their submission is correct. This allows authors to check a range of values or answers at once.

Thanks

We are hugely thankful for the 101 community members who have contributed pull requests, submitted translations, or reported issues since our last release. There are many more contributions and updates to this version of learnr that aren't covered in this post; be sure to check out the full list of changes.

Thank you also to the previous maintainer of learnr, Barrett Schloerke! (learnr is now maintained by me, Garrick Aden-Buie.)

🙏 Big thank you to all of our contributors:

@acarzfr, @acastleman, @adisarid, @agmath, @AlbertLeeUCSF, @andysouth, @annafergusson, @assignUser, @batpigandme, @bbitarello, @beatrizmilz, @bhogan-mitre, @bjornerstedt, @blaiseli, @Brunox13, @C4caesar, @caievelyn, @cderv, @chendaniely, @choonghyunryu, @chrisaberson, @coatless, @ColinFay, @cpsievert, @cswclui, @czucca, @davidkane9, @dcossyleon, @ddauber, @deepanshu88, @dfailing, @dmenne, @dputhier, @DrAtzi, @drmowinckels, @dtkaplan, @elimillera, @elmstedt, @emarsh25, @enoches, @ericemc3, @ethelpruss, @gadenbuie, @gaelso, @garrettgman, @gdkrmr, @gtritchie, @gvwilson, @helix84, @hyigit2, @ijlyttle, @indenkun, @jakub-jedrusiak, @jcheng5, @jennybc, @jhk0530, @joe-chelladurai, @johnbde, @jooyoungseo, @jtelleriar, @jtransue, @kaisamng, @KatherineCox, @kendavidn, @kevinushey, @lorenzwalthert, @ltl-manabi, @MAGALLANESJoseManuel, @MaralDorri, @markwsac, @MayaGans, @meatballhat, @mikelmadina, @mine-cetinkaya-rundel, @mpjashby, @mstackhouse, @mutlusun, @NinaCorrelAid, @nischalshrestha, @NuoWenLei, @petzi53, @plukethep, @profandyfield, @psads-git, @pseudorational, @RaymondBalise, @rossellhayes, @rundel, @schloerke, @shalom-lab, @shalutiwari, @siebrenf, @SilasK, @stragu, @themfrees, @tombeesley, @trestletech, @tvedebrink, @vnijs, @wch, and @yabellini.



rstudio/learnr documentation built on Sept. 6, 2024, 11:06 p.m.