learnr v0.11.0
Garrick Aden-Buie
Source:vignettes/articles/releases/learnr_v0-11-0.Rmd
learnr_v0-11-0.Rmd
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:
- Basque (eu) language support was contributed by Mikel Madina (#489)
- Portuguese (pt) language support was contributed by Beatriz Milz (#488, #551)
- Spanish (es) language support was contributed by Yanina Bellini Saibene (#483, #546)
- Turkish (tr) language support was contributed by Hulya Yigit and James J Balamuta ( #493, #554)
- German (de) language support was contributed by @NinaCorrelAid (#611, #612)
- Korean (ko) language support was contributed by Choonghyun Ryu (#634)
- Chinese (zh) language support was contributed by @shalom-lab (#681)
- Polish (pl) language support was contributed by Jakub Jędrusiak (#686)
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).
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.
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, exercises can now be chained together via chained setup chunks such that the setup of one exercise may depend on other exercises1, 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.
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) 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.
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.
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.
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.
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.
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.
The exercise editor also supports a few additional keyboard shortcuts:
The (magrittr) pipe
%>%
with Cmd / Ctrl + Shift + MThe assignment arrow,
<-
with Opt / Alt + -Cmd / Ctrl + Enter 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, 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.
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.
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.