is_even_broken <- function(x) {
result <- logical(length = length(x))
for (i in seq_along(x)) {
if (x[i] %% 2 = 0) {
result[i] <- FALSE
} else {
result[i] <- TRUE
}
}
result
}
is_even_broken(c(2, 4, 5, 9))Write a function
Write a function with multiple arguments, understand for loops, and practice defensive programming and vectorization.
If you use any AI tool, report its name and associated prompts next to your answers.
Any obvious AI answers un-flagged as such will not be considered.
Take 5 min to watch this video by Hadley Wickham, until 5 min.
Being lazy, instead of you doing the work, rely on the work of someone else | Hadley Wickham

Part 0 — Predict before you run
Before writing any function, make sure you can read R code. For each snippet below, write what you expect the output to be in the text block provided, then run the code to check. If you were wrong, explain why in 1–2 sentences.
What is the difference between these two snippets? Predict both outputs, then run.
for (i in c(10, 20, 30)) {
print(i * 2)
}for (i in seq_along(c(10, 20, 30))) {
print(i * 2)
}My prediction for snippet A:
Write here
My prediction for snippet B:
Write here
What is the key difference between the two, and when would each be useful?
Write here
This code has a bug. Do not run it yet. Identify the bug by reading alone, explain what it does wrong, then fix and run.
There are two problems
Aim: write a function is_divisible(x, n) that takes a numeric vector x and a single integer n, and returns a logical vector indicating whether each element of x is divisible by n.
For example:
is_divisible(c(9, 4, 6, 7), n = 3)
# Expected: TRUE FALSE TRUE FALSE
is_divisible(c(10, 15, 7), n = 5)
# Expected: TRUE TRUE FALSENote that is_divisible has two arguments. Think about what each one represents.
Part 1 — Pseudocode
Before writing any R code, describe the algorithm in plain English or bullet points. Your pseudocode should be detailed enough that someone who does not know R could follow it.
Part 2 — Build it step by step
Version 0: no function yet
Pick a fixed value of n (e.g. 4) and a fixed vector, of length 4 with a mix of even and odd numbers. Write code that checks divisibility without putting it inside a function. Follow your pseudocode.
Fill in the table below by hand (without running code) for the input x <- c(6, 5, 12, 7) and n <- 4.
| Iteration | i |
x[i] |
x[i] %% n |
result after this step |
|---|---|---|---|---|
| 1 | 1 | |||
| 2 | 5 | FALSE |
c(FALSE, FALSE) |
|
| 3 | 3 | |||
| 4 |
Then to check, you can add in the for loop a print statement such as:
print(paste("i: ", i, ", x[i]", x[i], ", result[i]: ", result[i]))Wrap it in a function
Convert your Version 0 code into is_divisible(x, n).
Remember that the last command in a function is returned.
Test it on at least three different inputs, including one where all elements are divisible and one where none are.
Part 3 — Including defensive programming
What happens if a user calls is_divisible(1:3, 3:4), is_divisible("hello", 3) or is_divisible(c(1, 2, 3), "a")?
Try it and describe what R does:
# try bad inputs here and observe the errorsWrite test at the beginning of the function to catch those errors
xnot being numericnnot being a single integer (hint:length(n) != 1)
The R code:
stop("Warning! some conditions are not fulfilled to continue bla bla \n")should help. It stops the execution and print the chosen message. To prevent a chunk to stop the rendering with a desired error, use the option
#| error: truePart 4 — Vectorization
Now that the for loop was a pain to set-up, we can use what is good at: vectorization
Replace all the for loop code with one line of vectorization
The result vector is not needed.
Bonus questions
Optional questions. You can wrap the new questions around the already written is_divisible() to benefit from the defensive programming already written.
Create a new function that returns the number of divisible items
Such as:
count_divisible(c(4, 8, 12), n = 4)
[1] 3Create another function so it returns the sum of even items
Such as:
sum_divisible(c(4, 8, 12), n = 4)
[1] 24